我一直在使用Swift协议,我正在试图弄清楚为什么这段代码不起作用......
protocol Animal {
var name: String {get}
var breed: String {get}
}
struct Bird: Animal {
var name: String
var breed: String
var wingspan: Double
}
protocol AnimalHouse {
var myAnimal: Animal! {get set}
}
class Birdhouse: AnimalHouse {
var myAnimal: Bird!
func isOpeningBigEnough() -> Bool {
return myAnimal.wingspan <= 5.0
}
}
编译器给我的问题是BirdHouse
不符合协议AnimalHouse
。如果您进行了跟进,它会告诉您myAnimal
需要输入Animal
类型,而我正在提供类型Bird
。显然,Bird
符合Animal
协议,但这还不足以使编译器满意。
我假设这是一个单行修复中的一个,其中诀窍是知道一行的位置。有人有什么建议吗?
(而且,是的,我可以将myAnimal
设为Animal
,然后在函数中将其转换为Bird
,但这似乎不必要地混乱。)
答案 0 :(得分:3)
编译器是对的。
写作时
protocol AnimalHouse {
var myAnimal: Animal! {get set}
}
您正在(以及其他人中)发表以下声明:
如果某个类型符合
AnimalHouse
,则可以放置一个Animal!
属性中的myAnimal
。
现在让我们看看如何定义Birdhouse
class Birdhouse: AnimalHouse {
var myAnimal: Bird!
...
}
myAnimal
上的类型为Bird!
。
并且您不能将Animal!
放在Bird!
类型的属性中。
因此Birdhouse
不尊重AnimalHouse
协议中承诺的内容。
答案 1 :(得分:2)
正如你在问题中所说的那样,你不能只从Bird
转发到Animal
。我建议将var更改为可选,因为AnimalHouse
可能在某些时候没有居民。
在我的实施中,非Bird
动物无法进入禽舍。
protocol AnimalHouse {
var myAnimal: Animal? {get set}
}
class Birdhouse: AnimalHouse {
var myAnimal: Animal? {
get{
return myBird
}
set(newanimal){
if let bird = newanimal as? Bird {
myBird = bird
}
}
}
private var myBird: Bird?
func isOpeningBigEnough() -> Bool {
return myBird?.wingspan <= 5.0
}
}
AnimalHouse
协议的进一步发展可能是将throws
添加到setter(not possible as of Swift 2.0),或者AnimalHouse
返回它可以容纳的动物类型。
protocol AnimalHouse {
var myAnimal: Animal? {get set}
func houses() -> Any
}
class Birdhouse: AnimalHouse {
func houses() -> Any {
return Bird.self
}
}
答案 2 :(得分:1)
也许你会对这种方法感到满意:
protocol Animal {
var name: String {get}
var breed: String {get}
}
struct Bird: Animal {
var name: String
var breed: String
var wingspan: Double
}
// Read from here
protocol House {
typealias Inhabitant
var inhabitant: Inhabitant! {get set}
}
class Birdhouse: House {
typealias Inhabitant = Bird
var inhabitant: Inhabitant!
func isOpeningBigEnough() -> Bool {
return inhabitant.wingspan <= 5.0
}
}
然后是&#39; House&#39;协议只能用作通用约束,即以下是不可能的:
let house: House = Birdhouse() // Compile-time error
但您可以执行以下操作:
func printHouseInhabitant<T: House>(house: T) {
print(house.inhabitant)
}
let house = Birdhouse()
house.inhabitant = Bird(name: "Unnamed", breed: "general bird", wingspan: 4.5)
printHouseInhabitant(house) // "Bird(name: "1", breed: "2", wingspan: 3.0)\n"