如何制作声明协议类型 属性 的协议?

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

我们唯一可以分配给 Squarefill 属性 的东西是实现 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 属性.