我试图从泛型类型继承,以便我可以将类型插入层次结构中:
class Foo < T:AnyObject > : T {}
但我收到错误
inheritance from non-protocol, non-class type 'T'
但是我确保T是一个类(即使我将AnyObject更改为其他类)。这是不可能的吗?
答案 0 :(得分:0)
如果由于多种原因你不知道它是什么,你就不能继承。
首先,编译器需要知道如何在内存中布置类的实例。要做到这一点,它需要知道它具有哪些实例变量(存储属性):类指定的那些和从超类继承的那些。
编译器还需要了解超类的属性和初始值设定项,以确保正确初始化类的实例。如果超类的属性是未知的,那么在初始化程序结束之前,无法知道您是否已初始化了应该进行的所有状态(并且没有一个你不应该这样做)。如果超类的初始化程序未知,则编译器无法强制您从自己的程序中调用超类“指定的初始化程序。”
如果您不知道超类是什么,您将如何编写引用超类属性和方法的方法实现?如果您编写引用self.view
的代码,那么以某种方式实例化您的类的一个版本,该版本不会从具有该属性的类继承,该代码将会中断。
可能还有其他几个原因,但这些原因应该足够了。 :)
虽然有一些地方需要你进行子类化,但Cocoa(无论是在Swift还是ObjC中)通常都支持composition而不是继承来进行自定义。
如果您要向各种视图控制器添加一堆功能,并通过将其分解到自己的类中来重用代码,那么简单的解决方案就是让您的视图控制器类全部拥有该类的实例,而不是尝试 该类。如果您想要强制某些视图控制器类必须拥有Foo
,您可以定义表达该要求的协议。
如果您尝试向现有类添加功能,则可以使用扩展名。您可能无法使用扩展来添加存储的属性,但您当然可以伪造它。例如,您可以使用计算属性,并在其实现中定义您自己的存储。一种方法可能是使用ObjC运行时的associated objects feature(仍然可以从Swift访问AFAIK)。
答案 1 :(得分:0)
不是CR的(Curiously recurring template pattern)与OP不同吗?
在Swift(&lt; = 3.0)中设计该模式是完全没问题的,但它目前存在漏洞,并且会在运行时锁定初始化而没有任何错误。
class Template<T> { ... }
class RealThing : Template<RealThing> { ... }
我最近在桥接的UIKit API中发现了这种模式。您可以在我的短文here中阅读。
我还将wiki中的示例翻译成了Swift 3.0:
protocol Constructor {
init()
}
protocol Shape {
func cloned() -> Shape
}
typealias ShapeProtocols = Constructor & Shape
class Shape_CRTP<T> : ShapeProtocols {
required init() {}
func cloned() -> Shape {
let new = Shape_CRTP<T>()
// copy everything to `new` from `self`
return new
}
}
extension Shape_CRTP where T : ShapeProtocols {
func cloned() -> Shape {
let new = T()
// copy everything to `new` from `self`
return new
}
}
// First non-crtp proof of concept
class Square : ShapeProtocols {
required init() {}
func cloned() -> Shape {
return Square()
}
}
let clone = Shape_CRTP<Square>().cloned() // creates a new `Shape`
type(of: clone) // Square.Type
// now CRTP but this is bugged: http://blog.devandartist.com/posts/swift-crtp
class Circle : Shape_CRTP<Circle> {}
Circle().cloned()
print("this will never print because of the described bug")