如果我将一个类作为子类,可以指定实例变量应为的某个子类吗?

时间:2018-08-10 20:12:15

标签: swift instance-variables subclassing

我有一个NSObject子类BaseClass。 BaseClass是一个占位符类,用于两个子类SubClassASubClassB。我在两个子类上都有一个实例变量。它们是相同的名称,并且都是另一个对象的对应子类。它们通常以非常相似的方式使用,因此我想将某些功能从SubClassA和SubClassB移到BaseClass。但是,我需要访问该变量。

如果将变量移到BaseClass中,则无法在SubClassASubClassB中指定变量的正确子类,说我无法覆盖它。如果我在BaseClass中使用此实例变量的公共父类,那么我将失去对SubClassASubClassB之间 不常见的东西的访问权限工作。

这是一个更原始的示例,但是我正在尝试做的基础。这个例子显然是行不通的。是我必须选择在SubClassASubClassB中定义通用功能的唯一选择,还是在这里实现我的目标的正确方法?

class BaseClass: NSObject {
    var myObject: MyObject
}

class SubClassA: BaseClass {
    override var myObject: MyObjectA
}

class SubClassB: BaseClass {
    override var myObject: MyObjectB
}

class MyObject: NSObject { }

class MyObjectA: MyObject { }

class MyObjectB: MyObject { }

这给了我错误:

  

类型为“ MyObjectA”的属性“ myObject”不能覆盖类型为“ MyObject”的属性

3 个答案:

答案 0 :(得分:4)

使用泛型怎么样?为了简单起见,我删除了NSObject

class MyObject {

}

class MyObjectA: MyObject {

}

class MyObjectB: MyObject {

}

class BaseClass<T> where T : MyObject {
    var myObject: T?
}

class SubClassA: BaseClass<MyObjectA> {
}

class SubClassB: BaseClass<MyObjectB> {
}

答案 1 :(得分:2)

您可以将其放入协议扩展中,而不是将与myObject相关的代码放入BaseClass中。考虑一下:

class BaseClass {
}

class SubClassA: BaseClass, HasMyObject {
    var myObject: MyObjectA
}

class SubClassB: BaseClass {
    var myObject: MyObjectB
}

class MyObject { }

class MyObjectA: MyObject { }

class MyObjectB: MyObject { }

protocol HasMyObject {
    associatedtype MyObjectClass

    var myObject: MyObjectClass { get set }
}

从概念上讲,这与使用泛型非常相似,但是会将您的myObject相关代码与类中的其余代码分开。是否实际上比泛型更可取取决于您的编码风格和特定的用例。

答案 2 :(得分:0)

您可以在BaseClass中创建一个类函数,该类函数返回一个继承自BaseObject(myObject)的类,并为您需要的任何类覆盖它。

class BaseClassObject: NSObject {

}

class BaseClass: NSObject {
    func generateClass() -> NSObject {
        return BaseClassObject()
    }
}

class BranchedObject: BaseClassObject {

}

class SubClassA: BaseClass {

    var myObject: NSObject?

    override func generateClass() -> NSObject {
        return BranchedObject()
    }

    override init() {
        super.init()
        self.myObject = self.generateClass()
    }

}