如何制作声明协议类型 属性 的协议?
How to make a protocol that declares a property of a protocol type?
我正在尝试利用 Swift 中的协议和扩展,但遇到了一个我无法理解的编译错误。
如果我像这样声明两个定义 Shape 的协议:
protocol Shape {
var sides : Int { get }
var fill : Fill { get }
}
protocol Fill {
var color : UIColor { get }
}
现在为了实现这个,我定义了两个结构,一个用于正方形,另一个用于实心填充。像这样:
struct SolidFill : Fill {
var color : UIColor
}
struct Square : Shape {
var sides : Int = 4
var fill : SolidFill = SolidFill(color: UIColor.blackColor())
}
我收到编译错误 "Type 'Square' does not conform to protocol 'Shape'"。如果我强制填充类型像 var fill : Fill
这样编译错误就会消失。为什么我不能让 Square 为填充指定更具体的类型,那么协议允许什么?
我意识到对于这个特定的示例,我可以通过使用 Enum 进行填充或修改其他内容来更改内容以不使用此模式。我只想知道为什么我不能让 fill 成为一个符合协议的类型。
只有一个 getter 理论上可能没问题,但如果有一个 setter 它肯定不能满足协议,因为有人可能会尝试设置一个不同的对象来满足协议。
如果您认为它足够有价值,您可以提出雷达要求它只获取变量,但您可能最好绕过它。
你可以这样做:
struct Square : Shape {
var sides : Int = 4
var fill : Fill { solidFill }
private var solidFill = SolidFill(color: UIColor.blackColor())
}
因为它没有意义。
在您开始编写符合协议的代码之前,您需要考虑您的协议并意识到在正常用例中(以及您的协议应该设计的方式),代码将只在具备以下知识的情况下编写协议,并且对实现该协议的任何特定 class 或结构的了解为零。
因此,Fill
协议有其他继承自它的协议是有意义的,例如 SolidFill
或许还有 StripedFill
.
让我们继续将 StripedFill
协议添加到您的示例中。现在让我们看看你的 Square
结构,看看为什么它没有实现 Shape
协议,这部分需要有一个 Fill
属性.
struct Square : Shape {
var sides : Int = 4
var fill : SolidFill = SolidFill(color: UIColor.blackColor())
}
我们唯一可以分配给 Square
的 fill
属性 的东西是实现 SolidFill
协议的东西。但是 Shape
协议要求我们的形状能够分配给一个叫做 fill
的 属性 任何符合 Fill
协议的东西。如果我们还有一个名为 StripedProtocol
的协议,它继承自 Fill
协议,它将包括实现该协议的 objects(无论它们是否也实现 SolidFill
协议)。
但是您的 Square
class 不允许这样做。您的 Square
class 只允许 Fill
及其后代中的一个特定 child,但不允许其兄弟……并排除 SolidFill
的潜力兄弟姐妹是你不能做你想做的事情的原因。
然而你可以做的是:
struct Square: Shape {
var sides: Int = 4
var fill: Fill = SolidFill(color: UIColor.blackColor())
}
所以在这种情况下,我们仍然肯定会为我们的 Square
分配 SolidFill
,但我们仍然允许 fill
属性 匹配它在协议中定义了什么,并允许将 SolidFill
的兄弟姐妹分配给 fill
属性.
我正在尝试利用 Swift 中的协议和扩展,但遇到了一个我无法理解的编译错误。
如果我像这样声明两个定义 Shape 的协议:
protocol Shape {
var sides : Int { get }
var fill : Fill { get }
}
protocol Fill {
var color : UIColor { get }
}
现在为了实现这个,我定义了两个结构,一个用于正方形,另一个用于实心填充。像这样:
struct SolidFill : Fill {
var color : UIColor
}
struct Square : Shape {
var sides : Int = 4
var fill : SolidFill = SolidFill(color: UIColor.blackColor())
}
我收到编译错误 "Type 'Square' does not conform to protocol 'Shape'"。如果我强制填充类型像 var fill : Fill
这样编译错误就会消失。为什么我不能让 Square 为填充指定更具体的类型,那么协议允许什么?
我意识到对于这个特定的示例,我可以通过使用 Enum 进行填充或修改其他内容来更改内容以不使用此模式。我只想知道为什么我不能让 fill 成为一个符合协议的类型。
只有一个 getter 理论上可能没问题,但如果有一个 setter 它肯定不能满足协议,因为有人可能会尝试设置一个不同的对象来满足协议。
如果您认为它足够有价值,您可以提出雷达要求它只获取变量,但您可能最好绕过它。
你可以这样做:
struct Square : Shape {
var sides : Int = 4
var fill : Fill { solidFill }
private var solidFill = SolidFill(color: UIColor.blackColor())
}
因为它没有意义。
在您开始编写符合协议的代码之前,您需要考虑您的协议并意识到在正常用例中(以及您的协议应该设计的方式),代码将只在具备以下知识的情况下编写协议,并且对实现该协议的任何特定 class 或结构的了解为零。
因此,Fill
协议有其他继承自它的协议是有意义的,例如 SolidFill
或许还有 StripedFill
.
让我们继续将 StripedFill
协议添加到您的示例中。现在让我们看看你的 Square
结构,看看为什么它没有实现 Shape
协议,这部分需要有一个 Fill
属性.
struct Square : Shape {
var sides : Int = 4
var fill : SolidFill = SolidFill(color: UIColor.blackColor())
}
我们唯一可以分配给 Square
的 fill
属性 的东西是实现 SolidFill
协议的东西。但是 Shape
协议要求我们的形状能够分配给一个叫做 fill
的 属性 任何符合 Fill
协议的东西。如果我们还有一个名为 StripedProtocol
的协议,它继承自 Fill
协议,它将包括实现该协议的 objects(无论它们是否也实现 SolidFill
协议)。
但是您的 Square
class 不允许这样做。您的 Square
class 只允许 Fill
及其后代中的一个特定 child,但不允许其兄弟……并排除 SolidFill
的潜力兄弟姐妹是你不能做你想做的事情的原因。
然而你可以做的是:
struct Square: Shape {
var sides: Int = 4
var fill: Fill = SolidFill(color: UIColor.blackColor())
}
所以在这种情况下,我们仍然肯定会为我们的 Square
分配 SolidFill
,但我们仍然允许 fill
属性 匹配它在协议中定义了什么,并允许将 SolidFill
的兄弟姐妹分配给 fill
属性.