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
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
.
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
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.
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()