Downcast from Any to a protocol

后端 未结 4 1215
南旧
南旧 2020-12-09 18:17

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

protocol Animal {
    func walk()
}

struct Cat: Animal {
    func walk() {}

    in         


        
相关标签:
4条回答
  • 2020-12-09 18:48

    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.

    0 讨论(0)
  • 2020-12-09 18:58

    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

    0 讨论(0)
  • 2020-12-09 19:06

    As far as I have been able to observe, AnyObject can only be downcast to an instances of class types(†) and Any 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"!

    (†) notable exceptions include being able to downcast from AnyObject to the core data types Int, String, etc.

    0 讨论(0)
  • 2020-12-09 19:11

    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()
    
    0 讨论(0)
提交回复
热议问题