我正在为一个学校项目制作框架,并且我决定将泛型用作每个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”无关。
答案 0 :(得分:0)
我认为,如果只对UIView进行子类化以创建Entity类,那么您会更好地构建类的层次结构。您是否需要使用泛型的特定原因?
我对发生的事情的猜测是,您已经定义了一个只能包含一个Entity的字典-当您尝试向其添加EntityPlay类时,它是一个imageView,这会导致此问题。如果您的字典被明确定义为可以接受[Any:Any],那么您可能可以解决此问题-但您必须解开包装中出现的所有结果,因为它们都是可选的。不用说,这将是一场噩梦。
答案 1 :(得分:0)
{
"type": "shell",
"inline": "mkdir /var/apps"
},
和EntityPlay
是不兼容的类型。设置泛型的类型时,您可以想象这是一个全新的类定义。
答案 2 :(得分:0)
侧栏注释:如果您打算从其类的外部调用addEntity
,则不能将其声明为private
。
问题:
调用view.addEntity(EntityPlay())
时出错的原因是:
addEntity
方法采用类型Entity<UIView>
的参数,它不是EntityPlay
类型的 ;换句话说,即使您将Entity<UIView>
≠Entity<UIImageView>
视为“但UIImageView
基本上是UIView
!”,但在处理泛型时就不是这种情况。 / p>
解决方案:
您可能需要创建一个抽象层来声明包含异构类型的集合。作为一种好习惯,您可以创建一个新协议,从而声明协议类型的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!!!