【问题标题】:Difference between abstract class and interface in Objective-CObjective-C中抽象类和接口的区别
【发布时间】:2015-02-25 17:53:07
【问题描述】:

iOS 开发者面试中最常见的问题之一是 - 抽象类和接口之间的区别。

我不知道答案,我也不明白。当您声明方法时,接口是类的一部分。它可以对其他类(公共、.h 文件)开放或隐藏在实现中。

抽象类是一个类,它只用于创建隐藏的子类,它不应该有自己的 init 方法(如果我理解正确的话)。

那么,这个问题的答案到底是什么?这个问题是什么意思?

我确实花时间寻找答案,但答案与 Obj-C 无关,所以我自己无法弄清楚。

我希望有人能提供明确的答案,这个问题对那些想通过面试的人有所帮助。

【问题讨论】:

  • 确切的答案是:ObjectiveC 没有抽象类...
  • @EvgeniyKleban 它们在概念上是抽象的,而不是在功能上抽象的。 Objective-C 不支持真正的抽象类,例如 Java。
  • @EvgeniyKleban “我无法回答这个问题,因为 ObjC 没有抽象类”正是正确的答案:D(“也许我正在面试错误的工作?你确实要求一个 Cocoa 开发者,对吧?”)
  • 旁注:虽然不可能在编译期间强制执行此操作,但(令人惊讶的是)可以在+load 时间(在大多数代码执行之前)强制执行此操作。尼克洛克伍德最近展示了一种技术。 github.com/nicklockwood/MustOverride。这有点疯狂,实际上很少见,但却是一个非常有趣和启发性的成就。
  • @Honey 接口不是抽象类。抽象类永远不应该被实例化;只有它们的子类是有意的。 .h 定义了一个类,但它不是抽象的。您当然打算创建该类型的实例。在您的示例中,在提供实现之前,根本无法编译该类。抽象类(在 C++/Java/etc 中)绝对可以在没有实现所有部分的情况下进行编译。他们只是不能被实例化。所以你所描述的在意图和机制上是不同的。

标签: objective-c


【解决方案1】:

解决这个问题的一个好方法是首先在一般编程理论中考虑它,然后在更具体的 Objective-C 上下文中考虑它。


抽象类 - 是一个纯粹用于子类化的类,不能实例化它。抽象类声明了一些东西,也有它的实现。

开设这样的特殊课程的原因是什么?它是根据现实生活建模的! :) 想象一个抽象——动物。 每种动物有什么共同点?他们都活着(并且可以死)。他们需要。可以在空间中移动。这些特征对所有动物来说都是共同的并且基本。我天堂没有听说过一种不需要食物,不能移动并且永远活着的动物。除此之外,各种动物之间存在很多不那么根本的差异。

地球上没有动物纯粹是抽象的动物。那一套基本的行为,特征根本不足以成为一个具体的动物。 有一个隐含的原则,即要成为一种具体的动物,除了那些基本特征之外,您还必须具有一些附加特征。

现在,在编程中,我们需要能够以某种方式

  • 表达这些基础知识(界面声明
  • 有一种描述它们如何工作的方式(实现
  • 将它们归于一个类
  • 防止实例化
  • 确保任何具体的动物都会拥有它们(继承

我们知道这些基础是什么(声明的公共接口),并且我们知道在实践中它们是如何具体体现的(这些声明的特征的实现)。我们希望它们被所有具体实体继承。所以我们在抽象类中这样做,因为它满足我提到的这些条件。它包含所有基础知识,有它们的实现,但不能单独实例化。

抽象类是对一组相关实体的抽象,它捕获所有实体之间的基本共同点。告诉我们它是如何完成的......并确保所有更具体的实体都将继承这一点。


界面 - 少一些。让我们来一个现实生活中的类比。人、机器人、动物、风(自然的力量)。 有些人会唱歌。机器人嵌入了语音合成器模块,因此它可以唱歌。我可以告诉你,触摸我露台玻璃的秋风“唱”了很多。还有 Tinka (r.i.p) 我的狗,其实也是个不错的歌手。

但实际上,这四个人之间的“歌唱”是唯一的共同点——你可以在耳朵里听到令人愉悦的声音。这四个人的歌唱方式在现实中很大不同。 (实施)

另一个问题是,当然不是所有的人、狗、风或动物都会唱歌。 有些可以。

那么我们将如何在编程中反映这种情况?通过接口:)

您可以拥有一个名为"SingInterface" 的接口,在我们的例子中,它声明了一个行为/特征/功能,它是sing。接口只是声明了一些东西,就是这样。接口并没有说明这件事是如何完成的,也没有具体的实现。也没有说谁能做到,接口中的 trait 并不局限于一种类型或一类。 (见http://www.nasa.gov/centers/goddard/universe/black_hole_sound.html

接口是 1 到 N 个特征/功能的列表,不知道它们将如何具体实现,并且可以任意(不存在谁的规则)可归因于来自不同集合的实体的特征/功能列表根本不同(动物或机器人)。

面向对象编程借鉴了现实生活中的许多概念。这就是为什么这些类比如此有效的原因。


在Objective C中,与其他一些语言(C#等)相反,

抽象类没有语言级别的支持。 不可能在编译期间强制一个类是抽象的。一个类只有按照约定是抽象的,并且开发人员尊重该约定。

关于接口,在objective C中使用了“协议”这个词。它只是同一事物的不同词。

在目标 C 中你可以

  • 针对接口的代码 ..通过将某个对象声明为

     id<protocolName>
    
  • 向类添加附加功能,通过声明它们符合您在类接口中执行的协议

    @interface ClassName <protocolName>
    

因此,甚至可能存在您的类是抽象类的子类,并且它也符合某些协议的情况。

【讨论】:

  • 答案不错!
  • @Earl Gray 太棒了!顺便说一句,你应该试着写一本书,我一定会喜欢的。
  • 这个答案值得更多投票!我尽了我的一份力! :-) 解释得真好!
  • 对这个概念的解释非常清楚! +1
  • 这么说有什么问题:接口是一个抽象类——对其.m文件。在.m 内部,我们实现了在我们的接口中编写的所有公共方法?我的意思是,如果.m 文件没有实现已经在其私有抽象类(又名接口)中声明的方法,它不会像您承诺实现的那样给出编译器错误但没有......除此之外是的抽象类和接口是非常不同的。或者是“接口只适用于一个单个实现文件”的区别导致了抽象类和接口的区别?
【解决方案2】:

感谢 Rob Napier 在here 的评论。我的回答是:

接口只是类的外部视图。它公开揭示了什么。

在 Swift 中,你只需在单个 .Swift 文件中编写一个类,如果让 Xcode 显示你可以 generate its interface。 Xcode 将显示公共/内部的属性/函数。

在 Objective-C 中。您首先必须手动编写接口...声明哪些类是公共的,然后手动编写实现。没有实现的接口是不可可编译的。就像你说这就是我的类的样子,但是你没有提供它如何实现公共方法或你如何操作你的属性——当你必须(提供)时。

Abstract 让您摆脱它是如何实现的

对于抽象类,您不应该提供任何实现,只要它具有此类参数或具有此类签名的此类功能即可。然而,抽象类可自行编译的。因为你不需要提供更多的东西。

【讨论】:

  • 关于 Swift 领域的这么好的解释!
猜你喜欢
  • 1970-01-01
  • 2010-09-27
  • 1970-01-01
  • 2011-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-27
  • 2014-01-20
相关资源
最近更新 更多