Примечание на боковой панели: если вы хотите позвонить 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!!!