Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 协议真的是超类的替代品吗?_Objective C_Swift - Fatal编程技术网

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

Objective c 协议真的是超类的替代品吗?,objective-c,swift,Objective C,Swift,我观看了WWDC15的面向协议的编程视频。在我看了这段视频后,我感到困惑。谁能给我一个相关的例子来说明这个想法 更多的协议扩展实际上是对操作符重载的替代。A.基本问题 想想这种情况: 您拥有与其他实例交互的类AAs必须知道其他实例所属类的API。有两种方法可以实现这一点: 其他实例是(可能是虚拟的)基类B和A知道该类B(通过导入或其他方式)。在这种情况下,a可以依赖于Bs的功能 其他实例实现协议B,A知道协议B(通过导入或其他方式)。在这种情况下,a也可以依赖Bs的功能 解决方案1的缺点是A

我观看了WWDC15的面向协议的编程视频。在我看了这段视频后,我感到困惑。谁能给我一个相关的例子来说明这个想法

更多的协议扩展实际上是对操作符重载的替代。

A.基本问题

想想这种情况:

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

  • 其他实例是(可能是虚拟的)基类
    B
    A
    知道该类
    B
    (通过导入或其他方式)。在这种情况下,
    a
    可以依赖于
    B
    s的功能
  • 其他实例实现协议
    B
    A
    知道协议
    B
    (通过导入或其他方式)。在这种情况下,
    a
    也可以依赖
    B
    s的功能
解决方案1的缺点是
A
指定了其他实例的(基类)。这可能会导致一个问题:首先,基类
B
无法适应。另外,
B
应该作为许多类的“助手”,而不仅仅是
A
。这将导致多重继承。不,不,不,没有人想要那个

多协议实现没有问题

B.子类化与授权+协议作为专门化模式

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

  • 子类化是白盒:子类比其他类知道得更多
  • 基类包含许多方法。应该覆盖的方法集是什么
通过协议(和委托),您可以改变这一点:只要基类想要被专门化,它就会将该方法放入协议中,并在需要专门信息时“调用”实现该协议的实例(向该协议的实现者发送消息)。另一个类可以(可选)实现该协议并充当specialator

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

C.更抽象

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

  • 协议声明了一组方法,一个API
  • 类声明一组方法、一个API并实现它们
所以两者的区别在于类是实现者


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

在动态类型语言(Ruby、Python、Javascript等)中,有一个“duck typing”的概念,它本质上说,对象的实际类型是什么并不重要,只要它响应某些方法即可。与检查?的
实例不同,您可以检查
对?
的响应,当您使用检查来确定是否可以调用方法时,这一点更为相关

协议只是duck类型的正式声明。由于您要求提供一个示例(代码是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
所有这些类都是
车辆
父类的子类可能没有意义,因为
喷气背包
的属性和实现细节与
自行车
非常不同。但是请注意,所有这些类都响应
goto(x,y)
方法。创建另一个也响应此方法的类(例如,
helposer
)是很容易的

现在假设我们正在使用这些类中的一个:

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

无论
车辆
自行车
,还是将来定义的其他类,此代码都可以工作,因为此代码调用的是协议方法而不是类型方法

它们并不意味着语法上的替换;它们意味着软件设计的替代。苹果正在推广协议的使用和采用,而不是创建从中继承的基类。由于可以使用默认实现,协议可以像超类一样工作。您缺少Swift为协议添加默认实现的功能。因此,它们可以通过采用它们来提供默认功能。是的,但这是特定于语言的。您可以在Objective-C中结合基类和协议来实现这一点。但是,我想描述一下通用优势。只是问题具体指的是WWDC的一段视频,苹果在视频中赞美面向协议编程的优点。该视频仅适用于Swift,并且仅因为默认的实施功能。Q列表标记为“objective-c Swift”。我假设OP想知道语言不可知论的解释。视频中介绍的是一种非常好的od技术,在Objective-C中很有名