Swift类型和良好的旧时尚分层单继承

时间:2016-05-04 21:14:27

标签: swift class inheritance

这是一个很好的旧时尚单继承OO类树的例子:

class Common {
    var foo:String = ""
    var bar:Int = 0
    // common behavior to deal with foo + bar
}

class SubA:Common {
    var yak:Double = 0.0
    // specialized behavior to deal with yak, foo, and bar
}

class SubB:Common {
    var baz:CGFloat = 1.0
    // specialized behavior to deal with baz, foo, and bar
}

非常简单。 Swift为我们提供了许多思考问题的新方法,但这仍然是一个非常常见的OO范例,并且通常值得使用。如果我想创建与这些交互的ViewControllers,它很有可能遵循相同的模式:

class CommonViewController:UIViewController {
    var model:Common!
    // common behavior to deal with the common behavior found in the Common superclass
}

class SubAViewController:CommonViewController {
    var model:SubA!
    // more methods to deal with the specializations that SubA provides
}

class SubBViewController:CommonViewController {
    var model:SubB!
    // more methods to deal with the specializations that SubA provides
}

同样,非常标准的构造。不幸的是,Swift的类型系统不允许它:

error: cannot override mutable property 'model' of type 'Common!' with covariant type 'SubA!'
    var model:SubA!

有一个容易解决的问题吗?我能想到的最简单的方法是将子ViewControllers作为:

class SubAViewController:CommonViewController {
    var subA:SubA {
        get {
            return self.model as! SubA
        }
        set {
            self.model = newValue
        }
    }
    // some behavior will need to use self.subA to get that type of data
}

class SubBViewController:CommonViewController {
    var subB:SubB {
        get {
            return self.model as! SubB
        }
        set {
            self.model = newValue
        }
    }
    // some behavior will need to use self.subA to get that type of data
}

这增加了2个必须要做的工作方法以及我的一些子类方法必须引用self.subBself.subA而不是{的约束。 {1}}。我开始研究如何使用协议和扩展来实现这一点,但我感觉我正在添加越来越多的箍来使解决方案成为我想要的。是否有一个更简单的解决方案可以与Swift一起使用来实现这种非常经典和常见的OO继承模式?

2 个答案:

答案 0 :(得分:1)

总之,你不能这样做。您必须添加具有不同类型的新属性,并为getter和setter提供被覆盖的属性。 类似的案例可以在这里找到:Overriding superclass property with different type in Swift

答案 1 :(得分:1)

任何强类和静态类型的面向对象语言都不允许您尝试做的事情,不仅仅是在Swift中。

考虑一个函数f来获取类型为CommonViewController的对象。例如,此函数可以使用新值(类model的实例)修改对象的变量Common

然后,您可以向f传递SubAViewController类型的值,这是合法的,因为其类型将是CommonViewController的子类型。当f为其属性model分配Common类型的新值时,这会违反modelSubAViewController的类型声明,这可能导致运行时间类型错误,这种语言不允许这样做。