Это требование почти наверняка указывает на проблему дизайна.Если какая-то часть вашей системы заботится о том, что реализует протокол, то протокол не захватывает весь интерфейс.Например, если в какой-то момент вы используете as? ClassA
, это опасное использование протоколов.
Невозможно иметь в Swift протокол, который я вижу, но не могу реализовать.Есть такие языки, как Go, где это возможно (хотя и не совсем так, как вы описали), но сегодня это невозможно в Swift.Как отмечает @MartinR, ответ Дж. Доу на самом деле ничего не меняет.Внешние стороны все еще могут просто реализовать оба протокола.
С учетом всего вышесказанного можно достичь вещей, очень похожих на то, что вы описываете.
Во-первых, и наиболее очевидно: используйте средства управления доступом.
private protocol MyProtocol {}
public class ClassA: MyProtocol {}
public class ClassB: MyProtocol {}
Это работает, если все классы и протокол находятся в одном файле.Если нет, поместите их все в рамки и используйте internal
вместо private
.Теперь ничто вне этого файла / модуля не может реализовать MyProtocol
.Ограничение состоит в том, что MyProtocol
также нельзя увидеть вне файла / модуля.
Это можно решить, подняв структуру:
public struct MyStruct: MyProtocol {
private let value: MyProtocol
public init(classA: ClassA) { value = classA }
public init(classB: ClassB) { value = classB }
// Methods to conform to MyProtocol by forwarding to value
}
С этим невозможносгенерируйте MyStruct
, который инициализируется чем угодно, кроме ClassA
или ClassB
.
В качестве альтернативы, если вы действительно буквально подразумеваете "ClassA или ClassB", это не структура или протокол.Это перечисление:
enum MyEnum {
case classA(ClassA)
case classB(ClassB)
}