协议真的是超类的替代品吗?

时间:2016-02-18 09:40:26

标签: objective-c swift

我观看了WWDC15中面向协议的编程视频。看完这段视频后,我感到很困惑。任何人都可以给我一个说明这个想法的相关例子吗?

更多的协议扩展是操作符重载的真正替代。

2 个答案:

答案 0 :(得分:1)

在动态类型语言(Ruby,Python,Javascript等)中,存在“duck typing”的概念,它实质上表示对象的实际类型无关紧要,只要它对某些特定的响应即可。方法。您可以检查instance_of?,而不是检查responds_to?,当您使用检查时确定是否可以调用方法。

协议只是鸭子类型的正式声明。因为你问了一个例子(代码是Ruby,它是动态类型的 - 如果你不熟悉Ruby,只需将其视为伪代码并想象所有类型为id并且返回值为void):

想象一下,我们正在建立一个模型运输模型。我们可能有几种不同的运输方式:

class Bicycle
  def goto(x, y)
    # Implementation details
  end
end

class Car
  def goto(x, y)
    # Implementation details
  end
end

class Boat
  def goto(x, y)
    # Implementation details
  end
end

class Jetpack
  def goto(x, y)
    # Implementation details
  end
end

所有这些类都可能没有意义成为Vehicle父类的子类,因为Jetpack将具有与Bicycle非常不同的属性和实现细节。但请注意,所有这些类都响应goto(x, y)方法。创建另一个类(例如Helicopter)也很容易响应这个方法。

现在假设我们正在使用其中一个类:

class Person
  def travel(vehicle, destination)
    vehicle.goto(destination.x, destination.y)
  end
end

此代码无论vehicleBicycleBoat还是将来定义的其他类,都会有效,因为此代码调用协议方法< / em>而不是类型方法

答案 1 :(得分:0)

一个。基本问题

想想这种情况:

您有类A的实例与其他实例交互。 A必须知道其他实例所属的类的API。有两种方法可以实现这一目标:

  • 其他实例属于(可能是虚拟的)基类BA知道类B(通过导入或其他)。在这种情况下,A可以依赖B的功能。
  • 其他实例实现协议BA知道协议B(通过导入或其他)。在这种情况下,A也可以依赖B的功能。

解决方案1的缺点是A指示其他实例的(基础)类。这可能会导致问题:首先,基类B无法适应。另外,也许B应该充当&#34;助手&#34;对于许多课程,不仅A。这将导致多重继承。不,不,不,没有人想要那个。

多协议实现没有问题。

B中。子类化与委托+协议作为专业化模式

在许多情况下,你会发现一个基类A,由于某些原因应该是专门的,我。即数据访问和提供。在基于类的编程语言中,您将找到(虚拟)基类A并将其子类化。除了A)中讨论的问题,你会发现其他一些问题:

  • 子类化是白色拳击:子类比其他类知道更多。
  • 基类包含许多方法。应该覆盖的方法集是什么?

使用协议(和委托),您可以更改:只要基类想要专门化,它就会将方法放入协议中并且&#34;调用&#34;当需要专门信息时,实现协议的实例(向该协议的实现者发送消息)。另一个类可以(可选地)实现此协议并充当指定者。

这称为委托,使用协议实现并替换子类。

℃。更抽象的

你可以用更抽象的方式看到:

  • 协议声明了一组方法,即API。
  • 类声明了一组方法,一个API,实现它们。

因此两者之间的区别在于类是实现者。

所以有一条经验法则:如果你关心实现某些东西,请使用子类,因为你可以从基类继承很多代码。如果您关心声明API,请选择一个协议(并在类中实现,而不是在子类中实现)。