oop - 接口VS 抽象类Class ( 常规OO )

  显示原文与译文双语对照的内容

最近我有两个电话面试,我被问及一个接口和一个抽象类之间的区别。 我已经解释了我可以想到的每个方面,但似乎他们在等我提及一些特定的东西,我不知道它是什么。

从我的经验来看,我认为如下。 如果我缺少一个要点,请告诉我。

磅:

接口中声明的每个方法都必须在子类中实现。 接口中只能存在事件,委托,属性( C# ) 和方法。 一个类可以实现多个接口。

抽象类:

只有抽象方法必须由子类实现。 抽象类可以有带有实现的普通方法。 抽象类也可以在事件,委托,属性和方法旁边有类变量。 一个类只能实现一个抽象类,因为non-existence中的Multi-inheritance是。

  1. 在这之后,面试官提出了一个问题"如果你有一个抽象的类,并且只有抽象方法? 这与接口有什么不同"我不知道答案,但我认为它是上面提到的继承?

  2. 另一位面试官问我,如果接口中有一个公共变量,这与抽象类有什么不同? 我坚持你不能在接口内有公共变量。 我不知道他想要听到什么,但他还是不满意。

另请参阅:

时间:

虽然你的问题表明它是针对"通用 oo"的,但它似乎关注于. NET 使用这些术语。

在. NET ( 类似于 Java ) 中:

  • 接口没有状态或者实现
  • 实现接口的类必须提供该接口的所有方法的实现
  • 抽象类可能包含状态( 数据成员) 和/或者实现( 方法)
  • 抽象类可以继承而不实现抽象方法( 尽管这样一个派生类是抽象的)
  • 接口可以是 multiple-inherited,抽象类不能是( 这可能是关键的具体理由来接口独立于abtract可以存在类- 它们允许多重继承,它移除的实现带来的许多问题提出了通用mis系统) 。

作为一般的OO术语,差异不一定是明确的。 例如有 C++ 程序员可能拥有类似的严格定义( 接口是抽象类的严格子集,不能包含实现),而有些可能认为具有一些默认实现的抽象类仍然是接口或者non-abstract类仍然可以定义接口。

事实上,有一个 C++ 成语叫做所在的Non-Virtual接口( NVI ) Non-Virtual种方法都是公共方法'thunk'私有虚更新法。

类比:当我在空军中时,我参加了飞行员训练,成为了 USAF ( 美国空军) 飞行员。 那时我没有资格飞行,而且不得不参加飞机类型训练。 我合格后,我是一个飞行员( 抽象类) 和一个C-141飞行员( 具体类别) 。 在我的一个工作分配中,我得到了额外的职责: 安全官员。现在我仍然是一名飞行员和一个C-141飞行员,但我也执行了安全官员的职责。 飞行员不是一个安全人员,其他人也可以这样做。

所有的USAF飞行员都必须遵守某些空中Force-wide规则,以及所有 C-141 ( 或者 F-16,或者 T-38 ) 飞行员'是'USAF飞行员。 任何人都可以成为安全人员。 因此,总结:

  • Pilot: 抽象类
  • C-141 Pilot: 具体类
  • ISafety官员:接口

添加的注意:这是为了帮助解释概念,而不是一个编码建议。 查看下面的各种评论,讨论很有趣。

我认为他们寻找的答案是基本的或者哲学上的差异。

当派生类共享抽象类的核心属性和行为时使用抽象类继承。 实际定义类的行为类型。

另一方面,接口继承是在类共享外部行为时使用的,这些行为不一定定义派生类。

为eg。一辆汽车和一辆卡车分享大量的核心属性和行为的一种汽车的抽象类,但他们也分享一些外围的行为像生成哪些甚至非汽车类喜欢Drillers或者PowerGenerators共享和不一定定义一辆汽车或卡车,这样汽车、卡车、司钻和PowerGenerator都可以分享相同的接口IExhaust的排气。

短:抽象的类,用来造型( 例如动物的类似的期待类层次结构的类可以是抽象类,该类人。Lion,虎可以具体派生类)

接口是为通信 2相似/非相似的类之间的类实现接口,它不关心自己的类型( 例如 高度可以是接口属性,可以由人,建筑,树实现。 不管你是否可以吃,你可以游泳,你可以死或者任何东西。 它只需要一个你需要高度( 在你的类中实现)的东西。

还有一些不同之处-

接口不能有任何具体实现。 抽象基类。这允许你在那里提供具体的实现。 这可以让抽象基类真正提供一个更严格的契约,wheras接口实际上只是描述如何使用一个类。 ( 抽象基类可以有定义行为的non-virtual成员,从而给基类作者提供更多的控制。)

一个类可以实现多个接口。 类只能从单个抽象基类派生。 这允许使用接口的多态层次结构,但不支持抽象基类。 这也允许pseudo-multi-inheritance使用接口。

抽象基类可以在v2+中修改而不破坏 API 。 对接口的更改正在破坏更改。

抽象基类不同,[C#/.NET Specific]接口可以应用于值类型( 结构体) 。 结构不能从抽象基类继承。 这允许在值类型上应用行为契约/用法准则。

继承
考虑一辆汽车和一个公共汽车。 他们是两个不同的车辆。 但是他们仍然分享一些共同的特性,比如方向盘,刹车,齿轮,引擎等。
因此,继承概念可以表示如下。


public class Vehicle {
 public Driver driver;
 public Seat[] seatArray;//In java and most of the Object Oriented Programming(OOP) languages, square brackets are used to denote arrays(Collections).
//You can define as many properties as you want here..
}

现在是自行车。


public class Bicycle extends Vehicle {
//You define properties which are unique to bicycles here..
 public Pedal pedal;
}

还有汽车。


public class Car extends Vehicle {
 public Engine engine;
 public Door[] doors;
}

这些都是关于继承的。 我们使用它们将对象分类为简单的基本形式和他们的孩子。

抽象类

抽象类是不完整的对象。 为了进一步理解它,我们再次考虑汽车模拟。
汽车可以被驱动。 对但是不同的车辆是以不同的方式驱动的。 例如你不能像驾驶自行车一样驾驶汽车。
如何表示车辆的驱动功能? 很难检查它是什么类型的车辆,并使用它自己的功能驱动它;在添加新类型的车辆时,你必须反复更改驱动程序类。
下面是抽象类和方法的角色。 你可以将驱动器方法定义为抽象,以表明每个继承的子级必须实现这里函数。
所以如果你修改了vehicle类。


//......Code of Vehicle Class
abstract public void Drive();
//.....Code continues

自行车和汽车还必须指定如何驾驶它。 否则代码将无法编译,并引发错误。
简而言之,抽象类是部分不完整的类,具有一些不完整的函数,继承子类必须指定它们自己的。

接口接口完全不完整。 它们没有任何属性。 它们只是表明继承子对象可以做一些事情。
假设你有不同类型的移动电话。 每一个都有不同的方法来完成不同的功能;例如: 打电话给某人。电话制造商指定如何做。 在这里,移动电话可以拨一个号码,也就是说,它是 dial-able 。 我们将它的表示为一个接口。


public interface Dialable {
 public void Dial(Number n);
}

在这里,Dialable的制造商定义如何拨打一个号码。 你只需要给它一个号码来拨号。


Dialable myPhone1 = new Dialable() {
 public void Dial(Number n) {
//Do the phone1's own way to dial a number
 }
}

Dialable myPhone2 = new Dialable() {
 public void Dial(Number n) {
//Do the phone2's own way to dial a number
 }
}

这里使用接口而不是抽象类,你不必担心它是属性。 Ex: 它有touch-screen或者拨号盘,是固定固定电话还是移动电话。 你只需要知道它是否是拨号的;它是 inherit(or implement)的接口。
开发人员通常使用接口来确保对象之间的interoperability(use interchangeably),只要它们共享一个公共函数( 就像你需要拨打一个电话或者移动电话一样,你只需要拨打一个号码) 。 简而言之,接口是抽象类的简单版本,没有任何属性。
另请注意,你可能 implement(inherit) 任意数量的接口为你想要的,但你可以只 extend(inherit) 一个父类。

;更多信息抽象类 vs 接口

面试官正在 barking 。 对于 C# 和Java这样的语言,有不同的地方,但在其他语言中,比如 C++ 。 OO理论并不区分两者,只是语言的语法。

抽象类是一个具有实现和接口( 纯虚方法)的类,它将被继承。 接口通常没有任何实现,但只有纯虚函数。

在 C# 或者Java中,没有任何实现的抽象类与接口中的接口和只能从其中继承的事实的接口不同。

通过实现接口,你实现了组合("has-a"关系) 而不是继承("is-a"关系) 。 这是一个重要的原则,当你需要使用接口来实现一个行为的组合而不是一个继承的时候。

用于. Net.

第二个面试官的回答也是第一个面试的答案。 抽象类可以具有实现,并且状态不能有接口。。

编辑:在另一个注意中,我甚至不会使用'子类'( 或者'继承'短语) 来描述'定义为实现'接口的类。 对于我来说,接口是一个类的定义,如果它已经被定义为'实现'接口,那么该类必须遵守。 它不继承任何东西。。 你必须自己添加所有东西。

从概念上讲,保持语言特定的实现,规则,好处和实现任何编程目标都可以使用 code/data/property, blah单个或者多个继承,单个继承或者多个继承

1-抽象( 或者纯抽象) 类是实现层次结构的一种方法。 如果你的业务对象看起来有些相似,那么表示一个父级的子( 层次结构) 类型只有继承/抽象类才会被使用。 如果你的业务模型没有层次结构,那么继承不应该被使用( 这里我讨论的不是编程逻辑 比如 一些设计模式需要继承) 。 从概念上讲,抽象类是实现面向对象的业务模型的一种方法,它与接口无关,实际上与接口无关,因为在实现时使用了抽象类,程序员通常强调编程,而程序员通常强调编码。 [Keep this in mind as well that Abstraction is different than Abstract Class] 。

2-接口是一个契约,它是由更多的函数之一表示的完整业务功能。 这就是为什么它被实现而不是继承。 业务对象( 层次结构的一部分) 可以有任意数量的完整业务功能。 它与抽象类无关,一般意味着继承。 例如一个人跑,大象也可以运行了一个鸟儿可以运行等等,所有这些具有不同层次的对象将实现该接口或者吃或者朗读接口运行。 不要进入实现,因为你可能实现它,因为它为实现这些接口的每个类型都有抽象类。 任何层次结构的对象都可以有一个 functionality(interface),它与它的层次结构无关。

我相信,接口还没有诞生,以实现多重继承或者曝光公共行为,和纯抽象类不到超过规则接口与之类似,但界面是一个功能,一个对象可以完成核心的结构( property+functionality ) ( 通过该接口的功能) 和抽象类表示的父证书层次来产生子进程拥有父进程

在特定于语言的实现,除非有人要求explicitly,当你被要求区分,它实际上是概念上的区别而不是不同的区别

我相信,这两个面试者也在等一行拉直前面这两个,并在你失败他们试图把你拉向着这种差异通过实现一个像之间的另一个区别

如果具有抽象方法的抽象类是什么?

...