oop - 物件導向方法相對於結構化方法的差異有哪些 - 物件導向解釋




界面與抽像類(通用OO) (20)

  1. 接口:
    • We do not implement (or define) methods, we do that in derived classes.
    • We do not declare member variables in interfaces.
    • Interfaces express the HAS-A relationship. That means they are a mask of objects.
  2. Abstract class:
    • We can declare and define methods in abstract class.
    • We hide constructors of it. That means there is no object created from it directly.
    • Abstract class can hold member variables.
    • Derived classes inherit to abstract class that mean objects from derived classes are not masked, it inherit to abstract class. The relationship in this case is IS-A.

This is my opinion.

最近我接到了兩次電話採訪,我被問到接口和抽像類之間的區別。 我已經解釋了他們所能想到的每個方面,但似乎他們正在等待我提及具體的事情,而我不知道它是什麼。

從我的經驗來看,我認為以下是事實。 如果我錯過了一個重點,請讓我知道。

接口:

在接口中聲明的每個方法都必須在子類中實現。 只有事件,委託,屬性(C#)和方法可以存在於接口中。 一個類可以實現多個接口。

抽像類:

只有抽象方法必須由子類實現。 一個抽像類可以有實現的普通方法。 抽像類也可以在事件,委託,屬性和方法旁邊有類變量。 由於C#中多重繼承的不存在,類只能實現一個抽像類。

  1. 畢竟,面試官想出了這樣一個問題:“如果你的抽像類只有抽象方法,那怎麼會和界面有所不同呢?” 我不知道答案,但我認為這是上面提到的繼承權嗎?

  2. 另一位面試官問我,如果你在界面中有一個公共變量,那麼這與抽像類有什麼不同呢? 我堅持說你不能在接口中使用公共變量。 我不知道他想听什麼,但他也不滿意。

另見


1) An interface can be seen as a pure Abstract Class, is the same, but despite this, is not the same to implement an interface and inheriting from an abstract class. When you inherit from this pure abstract class you are defining a hierarchy -> inheritance, if you implement the interface you are not, and you can implement as many interfaces as you want, but you can only inherit from one class.

2) You can define a property in an interface, so the class that implements that interface must have that property.

例如:

  public interface IVariable
  {
      string name {get; set;}
  }

The class that implements that interface must have a property like that.


Abstract class And Interface Difference :

  1. Abstract class can have abstract and non-abstract methods and Interface can have only abstract methods.
  2. Abstract class doesn't support multiple inheritance And Interface supports multiple inheritance.
  3. Abstract class can have final, non-final, static and non-static variables And Interface has only static and final variables.
  4. Abstract class can have static methods, main method and constructor And Interface can't have static methods, main method or constructor.
  5. Abstract class can provide the implementation of interface And Interface can't provide the implementation of abstract class.
  6. The abstract keyword is used to declare abstract class And The interface keyword is used to declare interface.
  7. Abstract class achieves partial abstraction (0 to 100%) because there are non abstract methods also in abstract class whereas interface achieves fully abstraction (100%).

Interface Types vs. Abstract Base Classes

Adapted from the Pro C# 5.0 and the .NET 4.5 Framework book.

The interface type might seem very similar to an abstract base class. Recall that when a class is marked as abstract, it may define any number of abstract members to provide a polymorphic interface to all derived types. However, even when a class does define a set of abstract members, it is also free to define any number of constructors, field data, nonabstract members (with implementation), and so on. Interfaces, on the other hand, contain only abstract member definitions. The polymorphic interface established by an abstract parent class suffers from one major limitation in that only derived types support the members defined by the abstract parent. However, in larger software systems, it is very common to develop multiple class hierarchies that have no common parent beyond System.Object. Given that abstract members in an abstract base class apply only to derived types, we have no way to configure types in different hierarchies to support the same polymorphic interface. By way of example, assume you have defined the following abstract class:

public abstract class CloneableType
{
// Only derived types can support this
// "polymorphic interface." Classes in other
// hierarchies have no access to this abstract
// member.
   public abstract object Clone();
}

Given this definition, only members that extend CloneableType are able to support the Clone() method. If you create a new set of classes that do not extend this base class, you can't gain this polymorphic interface. Also, you might recall that C# does not support multiple inheritance for classes. Therefore, if you wanted to create a MiniVan that is-a Car and is-a CloneableType, you are unable to do so:

// Nope! Multiple inheritance is not possible in C#
// for classes.
public class MiniVan : Car, CloneableType
{
}

As you would guess, interface types come to the rescue. After an interface has been defined, it can be implemented by any class or structure, in any hierarchy, within any namespace or any assembly (written in any .NET programming language). As you can see, interfaces are highly polymorphic. Consider the standard .NET interface named ICloneable, defined in the System namespace. This interface defines a single method named Clone():

public interface ICloneable
{
object Clone();
}

An interface defines a contract for a service or set of services. They provide polymorphism in a horizontal manner in that two completely unrelated classes can implement the same interface but be used interchangeably as a parameter of the type of interface they implement, as both classes have promised to satisfy the set of services defined by the interface. Interfaces provide no implementation details.

An abstract class defines a base structure for its sublcasses, and optionally partial implementation. Abstract classes provide polymorphism in a vertical, but directional manner, in that any class that inherits the abstract class can be treated as an instance of that abstract class but not the other way around. Abstract classes can and often do contain implementation details, but cannot be instantiated on their own- only their subclasses can be "newed up".

C# does allow for interface inheritance as well, mind you.


As you might have got the theoretical knowledge from the experts, I am not spending much words in repeating all those here, rather let me explain with a simple example where we can use/cannot use Interface and Abstract class .

Consider you are designing an application to list all the features of Cars. In various points you need inheritance in common, as some of the properties like DigitalFuelMeter, Air Conditioning, Seat adjustment, etc are common for all the cars. Likewise, we need inheritance for some classes only as some of the properties like the Braking system (ABS,EBD) are applicable only for some cars.

The below class acts as a base class for all the cars:

public class Cars
{
    public string DigitalFuelMeter()
    {
        return "I have DigitalFuelMeter";
    }

    public string AirCondition()
    {
        return "I have AC";
    }

    public string SeatAdjust()
    {
        return "I can Adjust seat";
    }
}

Consider we have a separate class for each Cars.

public class Alto : Cars
{
    // Have all the features of Car class    
}

public class Verna : Cars
{
    // Have all the features of Car class + Car need to inherit ABS as the Braking technology feature which is not in Cars        
}

public class Cruze : Cars
{
    // Have all the features of Car class + Car need to inherit EBD as the Braking technology feature which is not in Cars        
}

Consider we need a method for inheriting the Braking technology for the cars Verna and Cruze (not applicable for Alto). Though both uses braking technology, the "technology" is different. So we are creating an abstract class in which the method will be declared as Abstract and it should be implemented in its child classes.

public abstract class Brake
{
    public abstract string GetBrakeTechnology();
}

Now we are trying to inherit from this abstract class and the type of braking system is implemented in Verna and Cruze:

public class Verna : Cars,Brake
{
    public override string GetBrakeTechnology()
    {
        return "I use ABS system for braking";
    }       
}

public class Cruze : Cars,Brake
{
    public override string GetBrakeTechnology()
    {
       return "I use EBD system for braking";
    }         
}

See the problem in the above two classes? They inherit from multiple classes which C#.Net doesn't allow even though the method is implemented in the children. Here it comes the need of Interface.

interface IBrakeTechnology
{
    string GetBrakeTechnology();
}

And the implementation is given below:

public class Verna : Cars, IBrakeTechnology
{
    public string GetBrakeTechnology()
    {
        return "I use ABS system for braking";
    }
}

public class Cruze : Cars, IBrakeTechnology
{
   public string GetBrakeTechnology()
   {
       return "I use EBD system for braking";
   }        
}

Now Verna and Cruze can achieve multiple inheritance with its own kind of braking technologies with the help of Interface.


Couple of other differences:

Abstract classes can have static methods, properties, fields etc. and operators, interfaces can't. Cast operator allows casting to/from abstract class but don't allow casting to/from interface.

So pretty much you can use abstract class on its own even if it is never implemented (through its static members) and you can't use interface on its own in any way.


Difference between Java Interface and Abstract Class

  1. Main difference is methods of a Java interface are implicitly abstract and cannot have implementations. A Java abstract class can have instance methods that implements a default behavior.

  2. Variables declared in a Java interface is by default final. An abstract class may contain non-final variables.

  3. Members of a Java interface are public by default. A Java abstract class can have the usual flavors of class members like private, protected, etc..

  4. Java interface should be implemented using keyword “implements”; A Java abstract class should be extended using keyword “extends”.

  5. An interface can extend another Java interface only, an abstract class can extend another Java class and implement multiple Java interfaces.

  6. A Java class can implement multiple interfaces but it can extend only one abstract class.

  7. Interface is absolutely abstract and cannot be instantiated; A Java abstract class also cannot be instantiated, but can be invoked if a main() exists.

  8. In comparison with java abstract classes, java interfaces are slow as it requires extra indirection.


From another answer of mine , mostly dealing with when to use one versus the other:

In my experience, interfaces are best used when you have several classes which each need to respond to the same method or methods so that they can be used interchangeably by other code which will be written against those classes' common interface. The best use of an interface is when the protocol is important but the underlying logic may be different for each class. If you would otherwise be duplicating logic, consider abstract classes or standard class inheritance instead.


Interfaces are light weight way to enforce a particular behavior. That is one way to think of.


Though this question is quite old, I would like to add one other point in favor of interfaces:

Interfaces can be injected using any Dependency Injection tools where as Abstract class injection supported by very few.


如果你認為java是OOP語言來回答這個問題,那麼Java 8版本會導致以上答案中的一些內容過時。 現在java接口可以有具體實現的默認方法。

Oracle website提供了interfaceabstract類之間的關鍵區別。

考慮使用抽像類,如果:

  1. 你想在幾個密切相關的類中共享代碼。
  2. 您期望擴展您的抽像類的類具有許多常用的方法或字段,或者需要訪問修飾符而不是公共的(例如protected和private)。
  3. 您想要聲明非靜態或非最終字段。

考慮使用接口,如果:

  1. 你期望不相關的類將實現你的接口。 例如,許多不相關的對象可以實現Serializable接口。
  2. 您想要指定特定數據類型的行為,但不關心誰實現其行為。
  3. 你想利用類型的多重繼承。

簡單來說,我想用

接口:通過多個不相關的對象來實現合同

抽像類:在多個相關對像中實現相同或不同的行為

看看代碼示例以清晰的方式理解事情: 我應該如何解釋Interface和Abstract類之間的區別?


從概念上講,通過使用任何人或兩者來保持語言特定的實現,規則,好處和實現任何編程目標,可以或不能具有代碼/數據/屬性,等等,單個或多個繼承,

1-抽象(或純抽象)類是為了實現層次結構。 如果您的業務對像在結構上看起來有點類似,只表示父 - 子(層次)類型的關係,則將使用繼承/抽像類。 如果你的業務模型沒有層次結構,那麼就不應該使用繼承(這裡我沒有談論編程邏輯,例如一些設計模式需要繼承)。 從概念上講,抽像類是一種在OOP中實現業務模型層次結構的方法,它與接口無關,實際上將抽像類與接口進行比較是沒有意義的,因為兩者在概念上完全不同,在面試時只是要求檢查因為在執行過程中,它們看起來都提供了相同的功能,我們程序員通常更多地強調編碼。 [記住這一點,抽像是不同於抽像類]。

2-接口是一種合同,是由一組或多組功能表示的完整業務功能。 這就是為什麼它被實現,而不是繼承。 業務對象(或不是層次結構的一部分)可以具有任意數量的完整業務功能。 它與抽像類無關,一般意味著繼承。 例如,人可以運行,大象可以運行,鳥可以運行等,所有這些不同層次的對像都可以實現RUN界面或EAT或SPEAK界面。 不要進入實現中,因為您可能將它實現為具有實現這些接口的每種類型的抽像類。 任何層次結構的對像都可以具有與其層次結構無關的功能(接口)。

我相信,接口不是為了實現多重繼承或公開行為而發明的,類似地,純抽像類不是為了否定接口,而是接口是對象可以做的功能(通過該接口的功能),抽像類表示產生具有父母的核心結構(屬性+功能)的兒童的層級結構的父母

當你被問及差異時,除非明確詢問,否則它實際上是概念上的差異,而不是語言特定實現方面的差異。

我相信,兩位採訪者都希望這兩者之間有一條直線上的差異,當你失敗時,他們試圖通過實施ONE來推動你的這種差異

如果只有抽象方法的抽像類會怎麼樣?


怎麼樣呢?當我在空軍的時候,我參加了飛行員培訓,並成為了美國空軍(USF)的飛行員。 那時我沒有資格飛行任何東西,並且不得不參加飛機型訓練。 一旦我有資格,我是一名飛行員(抽象班)和一名C-141飛行員(具體班級)。 在我的一項任務中,我被賦予了額外的職責:安全官員。 現在我還是一名飛行員和一名C-141飛行員,但我也執行了安全主任職責(我實施了ISafetyOfficer,可以這麼說)。 飛行員不需要擔任安全官員,其他人也可以這樣做。

美國空軍的所有飛行員都必須遵守空軍的一些規定,所有C-141(或F-16或T-38)飛行員都是'美國空軍飛行員。 任何人都可以成為安全官員。 所以,總結一下:

  • 試點:抽像類
  • C-141飛行員:具體班級
  • ISafety Officer:接口

補充說明:這是為了幫助解釋這個概念,而不是編碼建議。 看到下面的各種評論,討論很有趣。


我認為他們不喜歡你的回答,因為你給出了技術上的差異而不是設計上的差異。 這個問題對我來說就像一個巨魔問題。 事實上,接口和抽像類有著完全不同的性質,所以你不能真正地比較它們。 我會告訴你我的界面是什麼,一個接口的作用是什麼,一個抽像類的作用是什麼。

接口:用於確保合同並在類之間進行低耦合,以便擁有更易維護,可擴展和可測試的應用程序。

抽像類:僅用於將相同可響應性的類之間的代碼分解。 請注意,這是多重繼承在OOP中是不好的主要原因,因為一個類不應該處理很多責任 (使用composition )。

所以接口具有真正的架構角色,而抽像類幾乎只是實現的一個細節(如果您正確使用它的話)。


我認為他們正在尋找的答案是OPPS的哲學差異。

當派生類共享抽像類的核心屬性和行為時,將使用抽像類繼承。 實際定義類的行為類型。

另一方面,當類共享外圍設備行為時使用接口繼承,而不一定定義派生類。

例如。 汽車和卡車共享汽車抽像類的許多核心屬性和行為,但它們也共享一些外圍行為,例如生成排氣,即使像Drillers或PowerGenerators這樣的非汽車類也共享並且不一定定義汽車或卡車,所以汽車,卡車,鑽機和PowerGenerator都可以共享IExhaust相同的界面。


簡而言之:抽像類用於建模類似外觀類的類層次結構(例如,Animal可以是抽像類,Human,Lion,Tiger可以是具體的派生類)

Interface用於2個相似/不相似的類之間的通信 ,它不關心實現Interface的類的類型(例如,Height可以是接口屬性,它可以由Human,Building,Tree實現。不管你是否可以吃,你可以游泳,你可以死或任何東西..它只是一個事情,你需要有高度(在你的課程實施))。


通過實現接口你正在實現組合(“有一個”關係),而不是繼承(“是一個”關係)。 當需要使用接口實現行為組合而不是繼承的設計模式時,這是一個重要的原則。


雖然你的問題表明它是針對“通用面向對象”的,但它似乎確實專注於.NET對這些術語的使用。

在.NET中(類似於Java):

  • 接口可以沒有狀態或實現
  • 實現接口的類必須提供該接口的所有方法的實現
  • 抽像類可能包含狀態(數據成員)和/或實現(方法)
  • 抽像類可以在不實現抽象方法的情況下繼承(儘管這樣的派生類本身是抽象的)
  • 接口可能是多重繼承的,抽像類可能不會(這可能是接口與abtract類分開存在的關鍵具體原因 - 它們允許實現多重繼承,從而消除了一般MI的許多問題)。

作為一般的OO術語,差異不一定是明確的。 例如,有些C ++程序員可能持有類似的嚴格定義(接口是抽像類的嚴格子集,不能包含實現),而有些人可能會說,具有某些默認實現的抽像類仍然是一個接口或非抽象類仍然可以定義一個接口。

事實上,有一種稱為非虛擬接口(NVI)的C ++習慣用法,其中公共方法是非虛擬方法,可以“虛擬”到私有虛擬方法:


對第二個問題的回答:默認情況下public定義的變量interfacestatic final默認的,而類中的變量是實例變量。publicabstract





abstract-class