Downcast from Any to a protocol

匿名 (未验证) 提交于 2019-12-03 01:14:02

问题:

I have the following code. How can I resolve the error in the last line?

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:

Update: This has been fixed in Swift 1.2+ (Xcode 6.3+). The Xcode 6.3 beta release notes say:

Dynamic casts (“as!", “as?" and “is”) now work with Swift protocol types, so long as they have no associated types.


You can only check for protocol conformance (which includes is, as, and as?) with an @objc protocol. Animal is not @objc.

See the Checking for Protocol Conformance section of the Swift book.

NOTE

You can check for protocol conformance only if your protocol is marked with the @objc attribute



回答2:

You can workaround it by doing

 var cat = obj as Cat as Animal 

but this workaround is almost useless... because you need to know the type of obj first


Edit:

As @newacct point out, it is not bug, see his answer for more information

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 protocol need @objc attribute and Cat need to be @objc class.



回答3:

My approach

@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:

As far as I have been able to observe, AnyObject can only be downcastAny can only be downcast to types (class or otherwise), it is not possible to cast them to a protocol.

I don't know if I would qualify this as a bug or not, if this holds then perhaps it was implemented this way for a good reason - but @Bryan's workaround (casting to a type first and then to a protocol) at least "resolves the error"!



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!