如何覆盖不同类型的超类属性

时间:2016-01-05 16:40:13

标签: swift

作为标题。 我知道。我可以使用[AnyObject]而不是类型变量,但我只想防止在swift中进行大量的类型检查。 现在,我对这个问题一无所知。有没有人可以帮助我。感谢

class TypeA: NSObject {
    var name: String
    ........
}
class TypeB: TypeA {
    .........
}
class ObjectA {
     var type = [TypeA]()
}
class ObjectB: ObjectA {
     override var type = [TypeB]() <---Cannot override a property "type"
}

问题更新:谢谢大家并参考“R Menke”的代码

class TypeA: NSObject {
    override init() {
        print("typeA")
    }
}
class TypeB: TypeA {
    override init() {
        print("typeB")
    }
}
class ObjectA<T:TypeA> {
    var type = [T]()
    init(type:T) {
        self.type.append(type)
       print("objectA")
    }

    func addNewType() {
        let newType = TypeA()
        self.type.append(newType)  <-- compiler complaints at here
    }

}
class ObjectB<T:TypeA>: ObjectA<T> {
    override init(type:T) {
        super.init(type: type)
       print("objectB")
    }
}

4 个答案:

答案 0 :(得分:2)

@RMenke在这里是完全正确的,但同样重要的是要理解为什么它是真的。这不是Swift的限制。这是子类意味着什么的基本问题。

让我们假装你能够做你想要的事情。如果这是真的,以下代码将是合法的:

let objA: ObjectA = ObjectB()
objA.type.append(ObjectA())

我必须被允许将ObjectB视为ObjectA。这就是Liskov Substitution Principle对于子类型的意义。所以现在我可以向ObjectA添加[ObjectB]。这打破了整个类型系统。 BLAM。

通常,当你想要这个时,那是因为你滥用了子类。子类很少是纯Swift中的正确工具;他们大多是因为与ObjC的桥接而陷入困境。但即使在ObjC中,也应尽可能避免子类化。 Swift给我们带来了很好的新工具来帮助避免子类,你应该更喜欢它们。例如,不要使用子类,而只使用协议:

protocol A {}
struct TypeA: A {}
struct TypeB: A {}

class Object<T: A> {
    var type = [T]()
}

答案 1 :(得分:1)

您不能在swift中覆盖存储的属性。但是,您可以在初始化实例时更改继承属性的值。

示例:

class TypeA: NSObject {
}

class TypeB: TypeA {
}

class ObjectA {
    var type = [TypeA]()
}

class ObjectB: ObjectA {
    override init() {
        super.init()
        type = [TypeB]()
    }
}

答案 2 :(得分:1)

您可以制作ObjectAObjectB个通用类。

class ObjectA<T:TypeA> {
    var type = [T]()

现在type属性始终是TypeATypeA的子类。 但是你不再需要垂头丧气来找出它是什么类型。

class TypeA: NSObject {
    override init() {
        print("typeA")
    }
}
class TypeB: TypeA {
    override init() {
        print("typeB")
    }
}
class ObjectA<T:TypeA> {
    var type = [T]()
    init(type:T) {
        self.type.append(type)
        print("objectA")
    }
}
class ObjectB<T:TypeA>: ObjectA<T> {
    override init(type:T) {
        super.init(type: type)
        print("objectB")
    }
}

let tA = TypeA()
let tB = TypeB()
let oA = ObjectA(type: tA) // ObjectA<TypeA>
let oB = ObjectB(type: tB) // ObjectB<TypeB>

或者只是让ObjectA通用:

ObjectB现在将作为ObjectA的特约者使用,它本身不是通用的,但会对其超类进行约束。现在你可以像任何其他类一样使用它,但它的type属性将TypeB作为类型而不是TypeA

class ObjectA<T:TypeA> {
    var type = [T]()
    init(type:T) {
        self.type.append(type)
        print("objectA")
    }
}
class ObjectB: ObjectA<TypeB> {
    override init(type:TypeB) {
        super.init(type: type)
        print("objectB")
    }
}

答案 3 :(得分:0)

另一个选择是在另一个中使用一个Class而不是使用继承。像这样:

class TypeA: NSObject {
}

class TypeB: TypeA {
}

class ObjectA {
    var type = [TypeA]()
}

class ObjectB: NSObject {
    private var obj = ObjectA()
    var type: [TypeB] {
        get{
            return obj.type as! [TypeB]
        }
        set {
            obj.type = newValue
        }
    }
}

var obj1 = ObjectB()
obj1.type = [TypeB()]
let test: TypeB = obj1.type[0]