Swift 协议:为什么编译器会抱怨我的 class 不符合协议?
Swift protocols: Why does the compiler complain that my class doesn't conform to a protocol?
我一直在研究 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
,但这似乎不必要地混乱。)
正如您在问题中所说,您不能只是从 Animal
向下转换为 Bird
。我建议将 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 () 或者 AnimalHouse
returns 它可以容纳的动物类型。
protocol AnimalHouse {
var myAnimal: Animal? {get set}
func houses() -> Any
}
class Birdhouse: AnimalHouse {
func houses() -> Any {
return Bird.self
}
}
也许你会对这样的做法感到满意:
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
}
}
但是 'House' 协议只能用作通用约束,即不可能:
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"
编译器是对的。
写的时候
protocol AnimalHouse {
var myAnimal: Animal! {get set}
}
您正在做出(除其他外)以下声明:
If a type does conform to AnimalHouse
, then it is possible to put an
Animal!
inside the myAnimal
property.
现在让我们看看Birdhouse
是如何定义的
class Birdhouse: AnimalHouse {
var myAnimal: Bird!
...
}
myAnimal
上的类型是 Bird!
。
而且您不能将 Animal!
放入 Bird!
.
类型的 属性 中
所以 Birdhouse
不 尊重 AnimalHouse
协议中的承诺。
我一直在研究 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
,但这似乎不必要地混乱。)
正如您在问题中所说,您不能只是从 Animal
向下转换为 Bird
。我建议将 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 (AnimalHouse
returns 它可以容纳的动物类型。
protocol AnimalHouse {
var myAnimal: Animal? {get set}
func houses() -> Any
}
class Birdhouse: AnimalHouse {
func houses() -> Any {
return Bird.self
}
}
也许你会对这样的做法感到满意:
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
}
}
但是 'House' 协议只能用作通用约束,即不可能:
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"
编译器是对的。
写的时候
protocol AnimalHouse {
var myAnimal: Animal! {get set}
}
您正在做出(除其他外)以下声明:
If a type does conform to
AnimalHouse
, then it is possible to put anAnimal!
inside themyAnimal
property.
现在让我们看看Birdhouse
是如何定义的
class Birdhouse: AnimalHouse {
var myAnimal: Bird!
...
}
myAnimal
上的类型是 Bird!
。
而且您不能将 Animal!
放入 Bird!
.
所以 Birdhouse
不 尊重 AnimalHouse
协议中的承诺。