创建从多个协议继承的协议类型的对象时出错
Error of creating an object of a protocol type which is inherited from multiple protocols
在下面的代码中,有3个协议:Wheeled
、Vehicle
和WheeledVehicle
(继承自Wheeled
和Vehicle
)
protocol Wheeled {
var numberOfWheels: Int { get }
}
protocol Vehicle {
var maker: String { get }
var owner: String {get set}
var ownerKid: String { get }
}
protocol WheeledVehicle: Wheeled, Vehicle {
// simply just combine Wheeled and Vehicle
}
class Bike: Vehicle, Wheeled {
let numberOfWheels: Int = 0
var ownerKid: String = "Junior"
var maker: String {
return "Ford"
}
var owner: String {
get {
return "Bob"
}
set {
ownerKid = "\(newValue) Junior"
}
}
}
let bike: Bike = Bike()
let wheeledVehicleBike: WheeledVehicle = bike //error: value of type 'Bike' does not conform to specified type 'WheeledVehicle'
问题:几乎是错误本身,我不明白,为什么类型 Bike
的值不符合指定类型 WheeledVehicle
非常感谢您的宝贵时间和帮助。
编译器不假定 "being wheeled" 和 "being a vehicle" 暗示 "being a wheeled vehicle"。可能是您的 WheeledVehicle
添加了新要求。
目前,编译器不做这种检查。老实说,这不应该,因为这会引入很多含糊不清的隐性行为,而且几乎没有什么好处。
您必须明确地将 Bike
设为 WheeledVehicle
基本上:因为不符合
要让编译器知道 Bike
符合 WheeledVehicle
,您必须指定它。编译器 不会 只是假设因为它们都遵循相同的协议,所以它们可以相互赋值。
同样的方法下面不行。
class A { var a : String = "" }
class B { var a : String = "" }
var a : A = A()
var b : B = a // cannot convert value of type 'A' to specified type 'B'
或者更简单
class A { }
class B { }
var a : A = A()
var b : B = a // cannot convert value of type 'A' to specified type 'B'
编译器不关心这两种类型是否相似——它们必须相似。
如果您的 WheeledVehicle
添加了 func
,您的示例会发生什么情况? Bike
不符合了吗?
使Bike
符合WheeledVehicle
的唯一方法是显式声明:class Bike : WheeledVehicle
!
继承只在一个方向起作用。例如,如果 Cat
继承自 Animal
,则 Cat
的实例是 Animal
的实例。但是 Animal
的实例不一定是 Cat
。
同样,在您的示例中,WheeledVehicle
的实例既是 Wheeled
的实例又是 Vehicle
的实例。但是既是 Wheeled
又是 Vehicle
的实例不一定是 WheeledVehicle
.
的实例
另一个注意事项:您可能会发现在代码中使用此表示法很方便:
let wheeledVehicleBike: protocol<Wheeled, Vehicle> = bike
这允许您指定一个类型符合的多个协议,而无需为此目的定义额外的协议。
在下面的代码中,有3个协议:Wheeled
、Vehicle
和WheeledVehicle
(继承自Wheeled
和Vehicle
)
protocol Wheeled {
var numberOfWheels: Int { get }
}
protocol Vehicle {
var maker: String { get }
var owner: String {get set}
var ownerKid: String { get }
}
protocol WheeledVehicle: Wheeled, Vehicle {
// simply just combine Wheeled and Vehicle
}
class Bike: Vehicle, Wheeled {
let numberOfWheels: Int = 0
var ownerKid: String = "Junior"
var maker: String {
return "Ford"
}
var owner: String {
get {
return "Bob"
}
set {
ownerKid = "\(newValue) Junior"
}
}
}
let bike: Bike = Bike()
let wheeledVehicleBike: WheeledVehicle = bike //error: value of type 'Bike' does not conform to specified type 'WheeledVehicle'
问题:几乎是错误本身,我不明白,为什么类型 Bike
的值不符合指定类型 WheeledVehicle
非常感谢您的宝贵时间和帮助。
编译器不假定 "being wheeled" 和 "being a vehicle" 暗示 "being a wheeled vehicle"。可能是您的 WheeledVehicle
添加了新要求。
目前,编译器不做这种检查。老实说,这不应该,因为这会引入很多含糊不清的隐性行为,而且几乎没有什么好处。
您必须明确地将 Bike
设为 WheeledVehicle
基本上:因为不符合
要让编译器知道 Bike
符合 WheeledVehicle
,您必须指定它。编译器 不会 只是假设因为它们都遵循相同的协议,所以它们可以相互赋值。
同样的方法下面不行。
class A { var a : String = "" }
class B { var a : String = "" }
var a : A = A()
var b : B = a // cannot convert value of type 'A' to specified type 'B'
或者更简单
class A { }
class B { }
var a : A = A()
var b : B = a // cannot convert value of type 'A' to specified type 'B'
编译器不关心这两种类型是否相似——它们必须相似。
如果您的 WheeledVehicle
添加了 func
,您的示例会发生什么情况? Bike
不符合了吗?
使Bike
符合WheeledVehicle
的唯一方法是显式声明:class Bike : WheeledVehicle
!
继承只在一个方向起作用。例如,如果 Cat
继承自 Animal
,则 Cat
的实例是 Animal
的实例。但是 Animal
的实例不一定是 Cat
。
同样,在您的示例中,WheeledVehicle
的实例既是 Wheeled
的实例又是 Vehicle
的实例。但是既是 Wheeled
又是 Vehicle
的实例不一定是 WheeledVehicle
.
另一个注意事项:您可能会发现在代码中使用此表示法很方便:
let wheeledVehicleBike: protocol<Wheeled, Vehicle> = bike
这允许您指定一个类型符合的多个协议,而无需为此目的定义额外的协议。