我正在为学校项目制作框架,并且我决定将泛型用作每个UIView的基线。我尝试将这些“实体”添加到通用字典中,该字典将采用“实体”类型。我尝试添加到此列表中的类名为“ EntityPlay”,并且是“ Entity”的子类。我尝试将此类添加到字典中,但是出现编译错误,指示“ EntityPlay”和“ Entity”不兼容。
我制定了实体的层次结构,并得出结论说“实体”实际上只是“实体”并没有任何错误。
public class View {
private var map : [Entity<UIView>]
private func addEntity<T : Entity<UIView>>(_ entity : T) -> Void {
self.map.append(entity)
}
}
public class Entity<T : UIView> {
some code
}
public class SomeClass {
public func someFunc() -> Void {
view.addEntity(EntityPlay())
}
}
public class EntityPlay : Entity<UIImageView> {
some code
}
我希望该代码在上述逻辑下可以完全正常工作,但是会导致编译错误,指示“ EntityPlay”与“ Entity”无关。
最佳答案
补充说明:如果要从类的外部调用addEntity
,则不能将其声明为private
。
问题:
调用view.addEntity(EntityPlay())
时发生错误的原因是:addEntity
方法采用类型Entity<UIView>
的参数,该参数不是EntityPlay
的类型。换句话说,即使您将Entity<UIView>
≠Entity<UIImageView>
认为是“但UIImageView
基本上是UIView
!”,但在处理泛型时就不是这种情况。
解:
您可能需要创建一个抽象层来声明包含异构类型的集合。作为一种好的做法,您可以创建一个新协议,从而声明协议类型的map
数组。例:
protocol EntityProtocol {
func doSomething()
}
public class View {
private var map : [EntityProtocol] = []
func addEntity<T : EntityProtocol>(_ entity : T) -> Void {
self.map.append(entity)
}
}
此时,您需要使
Entity
符合EntityProtocol
;因此,由于EntityPlay
是从Entity
继承的,因此它也隐式地符合EntityProtocol
:public class Entity<T : UIView>: EntityProtocol {
func doSomething() {
print("Entity!!")
}
}
public class EntityPlay : Entity<UIImageView> {
override func doSomething() {
print("EntityPlay!!!")
}
}
输出:
为了检查输出,让我们调用
addEntity
两次,将Entity
和EntityPlay
实例传递给它:public class SomeClass {
public func someFunc() -> Void {
let view = View()
// Entity
let entityView = Entity()
view.addEntity(entityView)
// EntityPlay
let entityPlay = EntityPlay()
view.addEntity(entityPlay)
// let's assume that `map` is public:
for e in view.map {
e.doSomething()
}
}
}
let test = SomeClass()
test.someFunc()
// Entity!!
//EntityPlay!!!
关于swift - 这个层次结构应该如何运作?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55816075/