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

时间:2015-11-10 13:20:04

标签: swift swift-protocols

我正在尝试利用Swift中的协议和扩展,但是我得到了一个我无法理解的编译错误。

如果我声明两个定义如下形状的协议:

protocol Shape {
  var sides : Int { get }
  var fill : Fill { get }
}

protocol Fill {
  var color : UIColor { get }
}  

现在要实现这个,我为一个Square定义了两个结构,另一个为实体填充。像这样:

struct SolidFill : Fill {
  var color : UIColor
}

struct Square : Shape {
  var sides : Int = 4
  var fill : SolidFill = SolidFill(color: UIColor.blackColor())
}

我收到编译错误" Type' Square'不符合协议' Shape'"。如果我强制填充类型填充var fill : Fill,编译错误就会消失。为什么我没有Square指定更具体的填充类型,那么协议允许什么?

我意识到,对于这个特定的例子,我可以通过使用Enum填充或重新编写其他东西来改变不使用此模式的东西。我只是想知道为什么我不能填写符合协议的类型。

2 个答案:

答案 0 :(得分:1)

因为没有意义。

在开始编写符合协议的代码之前,您需要考虑您的协议并意识到在正常使用情况下(以及协议的设计方式),代码将仅在协议知识下编写并且没有任何实现协议的特定类或结构的知识。

因此,Fill协议确实有其他协议继承它,例如SolidFillStripedFill

让我们继续并将StripedFill协议添加到您的示例中。现在让我们看看你的Square结构,看看为什么它没有实现Shape协议,这部分要求具有Fill属性。

struct Square : Shape {
  var sides : Int = 4
  var fill : SolidFill = SolidFill(color: UIColor.blackColor())
}

我们可以分配给Square的{​​{1}}属性的唯一内容是实现fill协议的内容。但是SolidFill协议要求我们的形状能够分配给符合Shape协议的任何名为fill的属性。在我们还有一个名为Fill的协议的情况下,该协议继承自StripedProtocol协议,其中包括实现该协议的对象(无论它们是否也实现Fill协议)

但是你的SolidFill课程不允许这样做。您的Square课程仅允许Square及其后代的一个特定孩子,但不允许其兄弟姐妹......并排除Fill潜在的兄弟姐妹是您无法做到的原因你想做什么。

你可以做的是:

SolidFill

所以在这种情况下,我们仍然肯定会为struct Square: Shape { var sides: Int = 4 var fill: Fill = SolidFill(color: UIColor.blackColor()) } 分配SolidFill,但我们仍然允许Square属性与协议中定义的属性相匹配并允许fill的兄弟姐妹被分配到SolidFill属性。

答案 1 :(得分:0)

只有一个吸气剂,理论上可能没问题但是如果有一个设定器,它肯定不会满足协议,因为有人可能会尝试设置一个满足协议的不同对象。

如果你认为它有足够的价值,你可以提出一个雷达,要求它只获得vars,但你可能更好地解决它。

你可以这样做:

struct Square : Shape {
  var sides : Int = 4
  var fill : Fill { solidFill }
  private var solidFill = SolidFill(color: UIColor.blackColor())
}