在Swift中使用不同的types覆盖超类属性
在Swift中,有人可以解释如何覆盖超类的属性与从原始属性的子类别的另一个对象?
以这个简单的例子:
class Chassis {} class RacingChassis : Chassis {} class Car { let chassis = Chassis() } class RaceCar: Car { override let chassis = RacingChassis() //Error here }
这给出了错误:
Cannot override with a stored property 'chassis'
如果我将底盘设置为“var”,则会出现以下错误:
Cannot override mutable property 'chassis' of type 'Chassis' with covariant type 'RacingChassis'
在“覆盖属性”下的指南中唯一可以find的指示是我们必须重写getter和setter,这可能会改变属性的值(如果它是'var'),但是改变属性类?
Swift不允许你改变任何variables或属性的类types。 相反,您可以在处理新类类的子类中创build一个额外的variables:
class Chassis {} class RacingChassis : Chassis {} class Car { var chassis = Chassis() } class RaceCar: Car { var racingChassis = RacingChassis() override var chassis: Chassis { get { return racingChassis } set { if newValue is RacingChassis { racingChassis = newValue as RacingChassis } else { println("incorrect chassis type for racecar") } } } }
看来不能用let语句声明一个属性,并且在它的子类中用var覆盖它,反之亦然,这可能是因为超类的实现可能不会期望那个属性在初始化后被改变。 所以在这种情况下,该属性需要在超类中声明'var'以及匹配子类(如上面的片段所示)。 如果无法更改超类中的源代码,那么在每次机箱需要发生变化时,可能最好销毁当前的RaceCar并创build一个新的RaceCar。
这似乎工作
class Chassis { func description() -> String { return "Chassis" } } class RacingChassis : Chassis { override func description() -> String { return "Racing Chassis" } func racingChassisMethod() -> String { return "Wrooom" } } class Car { let chassis = Chassis() } class RaceCar: Car { override var chassis: RacingChassis { get { return self.chassis } set { self.chassis = newValue } } } var car = Car() car.chassis.description() var raceCar = RaceCar() raceCar.chassis.description() raceCar.chassis.racingChassisMethod()
解决schemeDash提供的工作很好,除了超类必须用let关键字而不是var来声明。 这是一个可能的解决scheme,但不推荐!
下面的解决scheme将用Xcode 6.2,SWIFT 1.1(如果所有的类都在不同的swift文件中)编译,但是应该避免,因为它可能会导致意外的行为(包括一个CRASH,尤其是使用非可选types时)。 注意:这不适用于XCODE 6.3 BETA 3,SWIFT 1.2
class Chassis {} class RacingChassis : Chassis {} class Car { var chassis:Chassis? = Chassis() } class RaceCar: Car { override var chassis: RacingChassis? { get { return super.chassis as? RacingChassis } set { super.chassis = newValue } } }
尝试这个:
class Chassis{ var chassis{ return "chassis" } } class RacingChassis:Chassis{ var racing{ return "racing" } } class Car<Type:Chassis> { let chassis: Type init(chassis:Type){ self.chassis = chassis } } class RaceCar: Car<RacingChassis> { var description{ return self.chassis.racing } }
然后:
let racingChassis = RacingChassis() let raceCar = RaceCar(chassis:racingChassis) print(raceCar.description) //output:racing
理论上,你可以这样做…
class ViewController { var view: UIView! { return _view } private var _view: UIView! } class ScrollView : UIView {} class ScrollViewController : ViewController { override var view: ScrollView! { return super.view as ScrollView! } } class HomeView : ScrollView {} class HomeViewController : ScrollViewController { override var view: HomeView! { return super.view as HomeView! } }
这在Xcode游乐场中是完美的。
但是 ,如果你在一个真实的项目中尝试这个,编译器错误会告诉你:
声明“视图”不能覆盖多个超类声明
截至目前,我只检查Xcode 6.0 GM。
不幸的是,你必须等到苹果修复这个问题。
我也提交了一个错误报告。 18518795
我已经看到很多原因,为什么使用variables而不是函数来deviseAPI是有问题的,对于我来说,使用计算属性感觉就像是一个解决方法。 有很好的理由保持你的实例variables封装。 在这里,我创build了一个汽车符合的协议。 该协议具有返回Chassis对象的访问器方法。 由于Car符合它,RaceCar子类可以覆盖它并返回一个不同的Chassis子类。 这允许Car类编程到接口(Automobile),RaceChassis的RaceCar类可以直接访问_racingChassisvariables。
class Chassis {} class RacingChassis: Chassis {} protocol Automobile { func chassis() -> Chassis } class Car: Automobile { private var _chassis: Chassis init () { _chassis = Chassis() } func chassis() -> Chassis { return _chassis } } class RaceCar: Car { private var _racingChassis: RacingChassis override init () { _racingChassis = RacingChassis() super.init() } override func chassis() -> Chassis { return _racingChassis } }
为什么使用variables来deviseAPI的另一个例子是在协议中有variables的时候。 如果你想把所有的协议函数分解成扩展名,除了存储的属性不能放在扩展名中,并且必须在类中定义(为了编译,你必须取消注释代码AdaptableViewController类,并从扩展中删除模式variables):
protocol Adaptable { var mode: Int { get set } func adapt() } class AdaptableViewController: UIViewController { // var mode = 0 } extension AdaptableViewController: Adaptable { var mode = 0 // compiler error func adapt() { //TODO: add adapt code } }
上面的代码将有这个编译器错误:“扩展可能没有存储的属性”。 以下是如何重写上面的示例,以便协议中的所有内容都可以通过使用函数在扩展中分离出来:
protocol Adaptable { func mode() -> Int func adapt() } class AdaptableViewController: UIViewController { } extension AdaptableViewController: Adaptable { func mode() -> Int { return 0 } func adapt() { // adapt code } }
尝试这个:
class Chassis {} class RacingChassis : Chassis {} class SuperChassis : RacingChassis {} class Car { private var chassis: Chassis? = nil func getChassis() -> Chassis? { return chassis } func setChassis(chassis: Chassis) { self.chassis = chassis } } class RaceCar: Car { private var chassis: RacingChassis { get { return getChassis() as! RacingChassis } set { setChassis(chassis: newValue) } } override init() { super.init() chassis = RacingChassis() } } class SuperCar: RaceCar { private var chassis: SuperChassis { get { return getChassis() as! SuperChassis } set { setChassis(chassis: newValue) } } override init() { super.init() chassis = SuperChassis() } }
只需设置新的imageview属性与imgview不同的命名约定,因为imageView已经是它自己的属性,我们不能分配2强属性。
您可以简单地创build另一个RacingChassisvariables。
class Chassis {} class RacingChassis : Chassis {} class Car { let chassis: Chassis init(){ chassis = Chassis() }} class RaceCar: Car { let raceChassis: RacingChassis init(){ raceChassis = RacingChassis() }}