c# - 抽象函數和虛函數之間有什麼區別?




oop programming-languages (14)

  1. 只有abstract類可以有abstract成員。
  2. abstract類繼承的非abstract必須 overrideabstract成員。
  3. abstract成員是隱式virtual
  4. abstract成員不能提供任何實現( abstract在某些語言中稱為pure virtual )。

抽象函數和虛函數之間有什麼區別? 在哪些情況下,建議使用虛擬還是抽象? 哪種方法更為正確?


抽象函數不能有一個body,並且必須被子類覆蓋

虛擬功能將具有一個主體,可能會或可能不會被子類覆蓋


綁定是將名稱映射到代碼單元的過程。

後期綁定意味著我們使用該名稱,但推遲映射。 換句話說,我們首先創建/提及名稱,然後讓後續進程處理代碼到該名稱的映射。

現在考慮:

  • 與人類相比,機器非常擅長搜索和分類
  • 與機器相比,人類善於發明創新

所以,簡短的回答是: virtual是機器(運行時)的後期綁定指令,而abstract是人類(程序員)的後期綁定指令,

換句話說, virtual手段:

“親愛的運行時 ,通過做你最擅長的事情來將適當的代碼綁定到這個名字上: 搜索

abstract手段:

“親愛的程序員 ,請通過做你最擅長的事情來將適當的代碼綁定到這個名字上: 發明

為了完整性, 超載意味著:

“親愛的編譯器 ,通過做你最擅長的事情來將適當的代碼綁定到這個名字上: 排序 ”。


虛擬方法

  • 虛擬意味著我們可以覆蓋它。

  • 虛函數有一個實現。 當我們繼承這個類時,我們可以重寫虛函數並提供我們自己的邏輯。

  • 我們可以在執行時改變虛函數的返回類型
    在子類中的功能(可以說是一個概念
    陰影)。

抽象方法

  • 抽象意味著我們必須重寫它。

  • 抽象函數沒有實現並且必須位於抽像類中。

  • 它只能被宣布。 這迫使派生類提供它的實現。

  • 抽象成員是隱式虛擬的。 在某些語言中,抽象可以被稱為純虛擬。

    public abstract class BaseClass
    { 
        protected abstract void xAbstractMethod();
    
        public virtual void xVirtualMethod()
        {
            var x = 3 + 4;
        }
    } 
    

以我的理解:

摘要方法:

只有抽像類才能擁有抽象方法。 此外,派生類需要實現該方法,並且類中不提供任何實現。

虛擬方法:

一個類可以聲明這些並提供相同的實現。 此外派生類需要實現該方法來覆蓋它。


在C#中沒有什麼叫虛擬類。

對於功能

  1. 抽象函數只有簽名,驅動類應該用功能覆蓋。
  2. 虛擬功能將保留驅動類別根據要求可能或不可以覆蓋的功能部分

你可以根據你的要求來決定。


您必須始終重寫一個抽象函數。

從而:

  • 抽象函數 - 當繼承者必須提供自己的實現時
  • 虛擬 - 何時由繼承人決定

我在一些地方看到抽象方法的定義如下。 **

“抽象方法必須在子類中實現”

**我感覺就像。

如果子類也是抽象的不必在子類中實現抽象方法。

1)抽象方法不能成為私有方法。 2)抽象方法不能在同一個抽像類中實現。

我會說..如果我們正在實現一個抽像類,你必須重寫基抽像類的抽象方法。 因為..實現抽象方法是用覆蓋關鍵字。類似於虛擬方法。

虛擬方法不需要在繼承類中實現。

                                 ----------CODE--------------

public abstract class BaseClass
{
    public int MyProperty { get; set; }
    protected abstract void MyAbstractMethod();

    public virtual void MyVirtualMethod()
    {
        var x = 3 + 4;
    }

}
public abstract class myClassA : BaseClass
{
    public int MyProperty { get; set; }
    //not necessary to implement an abstract method if the child class is also abstract.

    protected override void MyAbstractMethod()
    {
        throw new NotImplementedException();
    }
}
public class myClassB : BaseClass
{
    public int MyProperty { get; set; }
    //You must have to implement the abstract method since this class is not an abstract class.

    protected override void MyAbstractMethod()
    {
        throw new NotImplementedException();
    }
}

抽象函數沒有實現,只能在抽像類中聲明。 這迫使派生類提供一個實現。 虛函數提供了一個默認實現,它可以存在於抽像類或非抽像類中。 例如:

public abstract class myBase
{
    //If you derive from this class you must implement this method. notice we have no method body here either
    public abstract void YouMustImplement();

    //If you derive from this class you can change the behavior but are not required to
    public virtual void YouCanOverride()
    { 
    }
}

public class MyBase
{
   //This will not compile because you cannot have an abstract method in a non-abstract class
    public abstract void YouMustImplement();
}

抽象函數(方法):

●抽象方法是一種用關鍵字abstract聲明的方法。

●沒有身體。

●它應該由派生類來實現。

●如果一個方法是抽象的,那麼該類應該抽象。

虛擬功能(方法):

●虛擬方法是使用關鍵字virtual聲明的方法,可以使用override關鍵字通過派生類方法覆蓋。

●派生類是否覆蓋它,取決於它。


抽象方法總是虛擬的。 他們不能有一個實現。

這是主要區別。

基本上,如果你有'默認'的實現並且想讓後代改變它的行為,你會使用一個虛擬方法。

用抽象的方法,你強迫後代提供一個實現。


抽象方法:當一個類包含抽象方法時,該類必須聲明為抽象。 抽象方法沒有實現,因此,從該抽像類派生的類必須為此抽象方法提供一個實現。

虛擬方法:一個類可以有一個虛擬方法。 虛擬方法有一個實現。 當您從具有虛擬方法的類繼承時, 可以覆蓋虛擬方法並提供其他邏輯,或者將邏輯替換為您自己的實現。

什麼時候使用:在某些情況下,你知道某些類型應該有一個特定的方法,但是,你不知道這個方法應該有什麼實現。
在這種情況下,您可以創建一個包含具有此簽名的方法的接口。 但是,如果您有這種情況,但您知道該接口的實現者也會有另一種常用方法(您可以為其提供實現),則可以創建一個抽像類。 這個抽像類包含抽象方法(必須被重寫)和另一個包含'common'邏輯的方法。

如果你有一個可以直接使用的類,但是你希望繼承者能夠改變某些行為,儘管它不是強制性的,那麼應該使用虛擬方法。


當你希望繼承者擴展他們想要的功能時,你基本上使用虛擬方法。

當你希望繼承者實現這個功能時你使用抽象方法(在這種情況下他們沒有選擇)


答案已經提供了很多次,但關於什麼時候使用的問題是設計時決定的。 我認為這是一種很好的做法,試圖將常見的方法定義捆綁到不同的接口中,並將它們拉入適當抽象層次的類中。 將一組通用的抽象方法和虛擬方法定義轉儲到類中時,可以最好地定義一個實現一組簡潔接口的非抽像類,從而使該類無法被收集。 一如既往,這取決於最適合您的應用程序特定需求的東西。





abstract