我观看了WWDC15中面向协议的编程视频。看完这段视频后,我感到很困惑。任何人都可以给我一个说明这个想法的相关例子吗?
更多的协议扩展是操作符重载的真正替代。
答案 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
此代码无论vehicle
是Bicycle
,Boat
还是将来定义的其他类,都会有效,因为此代码调用协议方法< / em>而不是类型方法。
答案 1 :(得分:0)
一个。基本问题
想想这种情况:
您有类A
的实例与其他实例交互。 A
必须知道其他实例所属的类的API。有两种方法可以实现这一目标:
B
,A
知道类B
(通过导入或其他)。在这种情况下,A
可以依赖B
的功能。 B
,A
知道协议B
(通过导入或其他)。在这种情况下,A
也可以依赖B
的功能。解决方案1的缺点是A
指示其他实例的(基础)类。这可能会导致问题:首先,基类B
无法适应。另外,也许B
应该充当&#34;助手&#34;对于许多课程,不仅A
。这将导致多重继承。不,不,不,没有人想要那个。
多协议实现没有问题。
B中。子类化与委托+协议作为专业化模式
在许多情况下,你会发现一个基类A
,由于某些原因应该是专门的,我。即数据访问和提供。在基于类的编程语言中,您将找到(虚拟)基类A
并将其子类化。除了A)中讨论的问题,你会发现其他一些问题:
使用协议(和委托),您可以更改:只要基类想要专门化,它就会将方法放入协议中并且&#34;调用&#34;当需要专门信息时,实现协议的实例(向该协议的实现者发送消息)。另一个类可以(可选地)实现此协议并充当指定者。
这称为委托,使用协议实现并替换子类。
℃。更抽象的
你可以用更抽象的方式看到:
因此两者之间的区别在于类是实现者。
所以有一条经验法则:如果你关心实现某些东西,请使用子类,因为你可以从基类继承很多代码。如果您关心声明API,请选择一个协议(并在类中实现,而不是在子类中实现)。