Отключить от Any до протокола
У меня есть следующий код. Как я могу разрешить ошибку в последней строке?
protocol Animal {
func walk()
}
struct Cat: Animal {
func walk() {}
init() { }
}
var obj: Any = Cat()
var cat = obj as Animal // ERROR: cannot downcast from Any to unrelated type Animal
Ответы
Ответ 1
Обновление:. Это было исправлено в Swift 1.2+ (Xcode 6.3+). В примечаниях к бета-версии Xcode 6.3 говорится:
Динамические трансляции ( "как!", "как?" и "есть" ) теперь работают с протоколом Swift типы, если у них нет связанных типов.
Вы можете проверить только соответствие протокола (включая is
, as
и as?
) протоколом @objc
. Animal
не @objc
.
Смотрите раздел Проверка соответствия протокола в книге Swift.
Примечание
Вы можете проверить соответствие протокола только в том случае, если ваш протокол отмечен с атрибутом @objc
Ответ 2
Вы можете обойти это, выполнив
var cat = obj as Cat as Animal
но это обходное решение почти бесполезно... потому что вам нужно знать тип obj
first
Edit:
Как @newacct указать, это не ошибка, см. его ответ для получения дополнительной информации
xcrun swift
Welcome to Swift! Type :help for assistance.
1>
2> @objc protocol Animal {
3. func walk()
4. }
@objc class Cat: Animal {
func walk() {}
init() { }
}
var obj: AnyObject = Cat()
var cat = obj as Animal
5>
6> @objc class Cat: Animal {
7. func walk() {}
8.
9. init() { }
10. }
11>
12> var obj: AnyObject = Cat()
obj: Cat = {}
13>
14> var cat = obj as Animal
cat: Cat = {}
15>
Animal
атрибут протокола @objc
и Cat
должен быть @objc class
.
Ответ 3
Мой подход
@objc protocol Animal {
func walk()
}
@objc class DummyAnimal: Animal {
func walk() {
}
}
@objc class Cat: DummyAnimal {
override func walk() {
print("meow")
}
override init() { }
}
var obj: Any = Cat()
var cat = obj as DummyAnimal
cat.walk()
Ответ 4
Насколько я мог наблюдать, AnyObject
может быть недоступен для экземпляров типов классов (†) и Any
может быть только downcast к типам (классу или иным образом), невозможно передать их в протокол.
Я не знаю, могу ли я квалифицировать это как ошибку или нет, если это выполняется, возможно, это было реализовано по уважительной причине - но обходное решение @Bryan (отведение к типу сначала, а затем к протоколу) по крайней мере, "разрешает ошибку"!
(†) примечательные исключения включают возможность перетаскивания из AnyObject в основные типы данных Int, String и т.д.