Swift从泛型类型继承

zac*_*caj 13 generics swift

我试图从泛型类型继承,以便我可以在层次结构中插入一个类型:

class Foo < T:AnyObject > : T {}
Run Code Online (Sandbox Code Playgroud)

但我得到错误

inheritance from non-protocol, non-class type 'T'
Run Code Online (Sandbox Code Playgroud)

但我确保T是一个类(即使我将AnyObject更改为其他类).这不可能吗?

ric*_*ter 0

由于多种原因,如果您不知道某物是什么,您就无法继承它。

  • 其一,编译器需要知道如何在内存中布置类的实例。为此,它需要知道它具有哪些实例变量(存储的属性):类指定的变量和从超类继承的变量。

  • 编译器还需要了解超类的属性和初始化程序,以确保正确初始化类的实例。如果超类的属性未知,则无法知道在初始化程序结束之前是否已经初始化了所有应该初始化的状态(并且没有初始化不应该初始化的状态)。如果超类的初始值设定项未知,则编译器无法强制您从自己的初始值设定项调用超类的指定初始值设定项。

  • 如果您不知道超类是什么,您将如何编写引用超类的属性和方法的方法实现?如果您编写引用 的代码self.view,然后以某种方式实例化不从具有该属性的类继承的类的版本,则该代码将会中断。

可能还有其他几个原因,但这些应该足够了。:)

尽管有一些地方需要子类化,但 Cocoa(无论是在 Swift 还是 ObjC 中)通常更喜欢组合而不是继承来进行定制。

如果您要向各种视图控制器添加一堆功能,并通过将其分解到自己的类中来重用此类代码,那么简单的解决方案是让您的视图控制器类都拥有该类的实例,而不是尝试那个班级。如果您想要强制某些视图控制器类必须拥有 a Foo,您可以定义一个协议来表达该要求。

如果您尝试向现有类添加功能,则可以使用扩展。您可能无法使用扩展来添加存储的属性,但您当然可以伪造它。例如,您可以使用计算属性,并在其实现中定义您自己的存储。一种方法可能是使用ObjC 运行时的关联对象功能(据我所知仍然可以从 Swift 访问)。