Протокол может быть соответствовали по нескольким лицам (в вашем случае, класс SubClass
), но сам протокол не знает о том, какие объекты, которые, соответствующие к нему. Поскольку ваш метод createFactory()
возвращает тип (протокол) IInterface
, а не тип SubClass
, возврат как есть не будет знать о членах, относящихся к SubClass
, даже если в качестве возврата отправлен объект SubClass
.
let mgr = Factory.createFactory() /* Type: let mgr: IInterface */
Это также очевидно при попытке вызова члена SubClassMethod
(или любой неизвестный элемент, скажем .foo
, для этого Metter) на экземпляре mgr
error: value of type 'IInterface' has no member 'SubClassMethod'
Чтобы обернуть его, тип, соответствующий протокол будет иметь доступ ко всем голубым методам и свойствам в этом протоколе, но экземпляр протокола, используемого в качестве типа (который является приемлемым, если у вас нет Я или каких-либо связанных типов в вашем протоколе) ничего не знает о методах и свойства других типов, которые соответствуют этому протоколу.
Как упомянуто ниже, если вы знаете возвращение типа IInterface
имеет определенный тип, то вы можете попытаться преобразование типа (as?
) к данному типу, например, ... as? SubClass
.Однако обратите внимание, однако, что протокол IInterface
не знает о том, какие типы, которые ему соответствуют, преобразованию этого типа нельзя утверждать как успешное во время компиляции; это строго что-то, что можно контролировать как разработчик, возможно, приводя к исключениям во время выполнения, если вы не будете осторожны (например, используя небезопасные методы, такие как принудительное преобразование as!
). Теперь, если функция всегда возвращает SubClass
типа, вы можете также изменить свою подпись
class func createFactory() -> SubClass {
Как возможное использование при держа IInterface
возвращение если createFactory()
на самом деле возвращает различных типов, что все соответствуют к IInterface
протокол. В этом случае можно смело использовать switch
блок над createFactory()
возвращения выполнить преобразование типа для Вас различных известных типов (известных разработчиком), которые соответствуют IInterface
следующего
protocol IInterface {
func InterfaceMethod() -> Void
}
public class SubClass: IInterface {
init() {}
func InterfaceMethod() { }
public func SubClassMethod() { }
}
public class AnotherClass: IInterface {
init() {}
func InterfaceMethod() { }
public func AnotherClassMethod() { }
}
public class Factory {
class func createFactory() -> IInterface {
if arc4random_uniform(5) > 2 {
return SubClass()
}
else {
return AnotherClass()
}
}
}
switch
блока над возвратом, когда вам звонит фабричный метод:
switch(Factory.createFactory()) {
case let mgr as SubClass:
print("Subclass")
mgr.SubClassMethod()
case let mgr as AnotherClass:
print("AnotherClass")
mgr.AnotherClassMethod()
// default case
case let mgr as IInterface:
print("Unknown specific regarding return type")
}
Наконец, возможно, ответ на следующий вопрос SO может иметь значение для вас
Основная проблема в этом ответе заключается в том, что собаки 'EvilDog' отвечают на' .sit() ', это не вероятное поведение. Возможно, добавьте свойство 'var obedient: Bool = true' в' Dog' и переверните на 'false' для' EvilDog', после чего изменив функцию '.sit()', чтобы вернуть логическое значение, являющееся этим свойством 'obedient'. Шутки в сторону, хорошая почта, +1! ;) – dfri