Отключить от 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 и т.д.