Необходимо удовлетворить требование протокола Swift, используя определенный подкласс требования (или тип, который ему соответствует) - PullRequest
3 голосов
/ 19 марта 2019

У меня есть протокол, который я создал (в Swift 4.2), и одно из его требований - это свойство того же типа, что и сам протокол.

Например, у меня есть протокол, определенный так:

protocol A {
    var a: A? { get set }
}

У меня есть несколько моделей, которые соответствуют этому протоколу:

class Model1: A {
    var a: A?
}
class Model2: A {
    var a: A?
}

Для одной из моих моделей мне нужно удовлетворить требования протокола, более точно указав свойство, определенное переменной a (т.е. переменная с типом протокола). Так, например, я могу захотеть реализовать Model2 как:

class Model2: A {
    var a: Model1?
}

В этом случае, поскольку Model1 соответствует протоколу A, можно ожидать, что он сможет удовлетворить требования протокола, однако вместо этого я получаю сообщение об ошибке:

Тип «Модель2» не соответствует протоколу «А»

Почему это происходит, и что я могу сделать, чтобы это работало, как описано выше?

Приложение

Я смоделировал вышеупомянутый сценарий в Игровой площадке XCode, и вот скриншот ошибки, которую я вижу. enter image description here

Ответы [ 2 ]

5 голосов
/ 19 марта 2019

Чтобы соответствовать протоколу A, Model2 потребуется член var a, который позволяет хранить ссылку на что-нибудь , соответствующее протоколу A, а не просто ссылку на Model1. Так что вы не можете сделать это.

4 голосов
/ 19 марта 2019

Вы можете сделать это с помощью связанных типов:

protocol A {
    associatedtype B: A
    var a: B? { get }
}

Это позволит вам объявить Model2 с желаемой спецификой:

class Model2: A {
    var a: Model1?
}

Но, к сожалению, это будет означать, что вы не сможетебольше объявлять переменные типа A.Чтобы исправить это, вы можете использовать общие модели:

class Model1<T: A>: A {
    var a: T?
}
...