Как эта иерархия должна функционировать? - PullRequest
0 голосов
/ 23 апреля 2019

Я делаю Framework для школьного проекта, и я решил использовать Generics в качестве основы для каждого 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».

Ответы [ 3 ]

0 голосов
/ 23 апреля 2019

EntityPlay и Entity не являются совместимыми типами. Когда вы устанавливаете тип универсального шаблона, вы можете представить, что это совершенно новое определение класса.

0 голосов
/ 23 апреля 2019

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

Я думаю, вам лучше было бы построить иерархию классов, если бы вы просто создали подкласс UIView для создания вашего класса Entity.Есть ли конкретная причина, по которой вам нужно использовать дженерики?

Я предполагаю, что вы определили словарь, который может принимать только Entity - когда вы пытаетесь добавить к нему класс EntityPlay, это imageView, который вызывает эту проблему.Если бы ваш словарь был явно определен, чтобы иметь возможность принимать [Любой: Любой], вы, вероятно, могли бы обойти это - но вам нужно было бы развернуть все результаты, которые были из него, поскольку все они были бы необязательными.Излишне говорить, что это будет кошмар.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...