0

I want to ensure by compiler that CarViewController only receives a Car in the vehicle property.

Given the following swift example code:

class Vehicle {
    func doSomething(){}
}

class Car: Vehicle {
    func doCarThings(){}
}

class VehicleViewController : UIViewController {
    var vehicle : Vehicle!;

    override func viewDidLoad() {
        super.viewDidLoad();
        vehicle.doSomething();
    }
}

class CarViewController:VehicleViewController {
    var vehicle: Car!

    override func viewDidLoad() {
        super.viewDidLoad();
        vehicle.doCarThings();
    }
}

I get the following error: Cannot override mutable property 'vehicle' of type 'Vehicle!' with covariant type 'Car!'

I tried with a generics-based approach:

class Vehicle {
    func doSomething(){}
}

class Car: Vehicle {
    func doCarThings(){}
}

class VehicleViewController<T:Vehicle> : UIViewController {
    var vehicle : T!;

    override func viewDidLoad() {
        super.viewDidLoad();
        vehicle.doSomething();
    }
}

class CarViewController:VehicleViewController<Car> {
    override func viewDidLoad() {
        super.viewDidLoad();
        vehicle.doCarThings();
    }
}

It is correct but using generics in storyboard classes results in errors (since they get compiled to objective-c).

How can I do this without using generics?

Thanks!

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Addev
  • 31,819
  • 51
  • 183
  • 302
  • Possible Dublicate of http://stackoverflow.com/questions/24094158/overriding-superclass-property-with-different-type-in-swift – hament miglani May 12 '17 at 12:35

2 Answers2

0

Taken from here:

Overriding Property Getters and Setters

You can provide a custom getter (and setter, if appropriate) to override any inherited property, regardless of whether the inherited property is implemented as a stored or computed property at source. The stored or computed nature of an inherited property is not known by a subclass—it only knows that the inherited property has a certain name and type. You must always state both the name and the type of the property you are overriding, to enable the compiler to check that your override matches a superclass property with the same name and type.

Seems like you cant do that.

Community
  • 1
  • 1
0

I'm really not sure about the design here, but to accomplish what you want you could do:

class CarViewController: VehicleViewController {
    var vehicleAsCar: Car { return self.vehicle as! Car }

    override func viewDidLoad() {
        super.viewDidLoad();
        vehicleAsCar.doCarThings();
    }
}

But this seems very smelly. Safer night be:

class CarViewController: VehicleViewController {
    override var vehicle: Vehicle! {
        didSet {
            assert(vehicle is Car, "Attempt to set vehicle to non-Car")
        }
    }
    var vehicleAsCar: Car { return self.vehicle as! Car }

    override func viewDidLoad() {
        super.viewDidLoad();
        vehicleAsCar.doCarThings();
    }
}
Grimxn
  • 22,115
  • 10
  • 72
  • 85