2016-07-26 61 views
0

我想我可能會將C++與C#混合在一起,但我不明白爲什麼在這個C#代碼中它們重新調用超類base()。並非所有東西都已經繼承了嗎?如何調用與繼承不同的類的base()

class Animal 
    { 
     public double height{get;set;} 

     public Animal() 
     { 
     this.height=0; 
     } 

    class Dog:Animal 
    { 
     public string favFood{get;set;} 

     public Dog():base() //Why not just omit the base? Doesn't dog inherit already from Animal? 
     { 
     this.favFood="No favorite food"; 
     } 
    } 
    } 
+1

你是對的。沒有必要明確地調用基礎構造函數。但是,如果'Animal'構造函數需要傳入參數,則可以通過像'base'這樣的調用來傳遞它們。 – itsme86

+2

'base()'不會使它繼承某些東西 - 它只是鏈接到基類構造函數。在這種情況下,它不是必需的,但如果使用參數鏈接到構造函數,則需要。 –

+0

你爲什麼不擺脫對':base()'的調用,看看會發生什麼? –

回答

0

所有構造函數都必須調用其基類型的構造函數。只要C#允許你忽略對base()的調用,只要在基類型中有一個默認構造函數即可。然而,當你的代碼被編譯時,默認情況下對基礎構造函數的調用會被插入。 (請記住,一切都在C#是一個對象,所以在技術上甚至Animal被調用到它的基類型的構造函數,但沒有明確的base()調用它總是調用到System.Object的默認構造函數。

base關鍵字開始派上用場當基類型具有非默認構造,因爲這可以讓你確定要調用哪個構造。

class Animal 
{ 
    private readonly string name; 
    public double height{get;set;} 

    public Animal(string name) 
    { 
    this.name = 0; 
    this.height=0; 
    } 

class Dog:Animal 
{ 
    public string favFood{get;set;} 

    public Dog():base("Fido") 
    { 
    this.favFood="No favorite food"; 
    } 
} 

}

在上述例子中,name只能由設置的構造函數,因此Dog必須通過base()關鍵字向該構造函數發送一個值。

0

想想以下幾點。在這種情況下,Animal具有一個帶有一個double類型參數的構造函數。因爲,Dog繼承Animal應提供此參數的基類的構造

class Animal 
{ 
    public double Height { get; set;} 

    public Animal(double height) 
    { 
     Height = height; 
    } 
} 

class Dog: Animal 
{ 
    public string FavoriteFood { get; set; } 

    public Dog(double height): base(height) 
    { 
     FavoriteFood = "No favorite food"; 
    } 
} 

在你的情況,因爲已經都itsme86和喬恩斯基特已經提到的,你不必使用: base(),因爲你的基本構造是參。

0

base()你所談論的是指定的基類的構造函數,其調用語句,這樣一來,如果你曾經爲基地的兩個不同的構造函數你可以選擇要執行:

class Animal 
{ 
    public double Height{get;set;} 
    public string Name {get; private set;} 

    public Animal() 
    { 
    this.height=0; 
    } 

    protected Animal(string name) 
    { 
    Name=name; 
    } 
} 

class Dog : Animal 
{ 
    public string FavoriteFood{get;set;} 

    //this calls the constructor with name parameter 
    public Dog(string name):base(name) 
    { 
    this.FavoriteFood="No favorite food"; 
    } 

    //this one calls the parameterless constructor 
    //this is optional, if its not included then 
    //behaves the same as : base() 
    protected Dog(int height):base() 
    { 
    this.favFood="No favorite food"; 
    } 
} 

這句法也可以用來調用同一類的其他構造函數,如果你有一個參數的構造函數和希望的參數默認設置

//this construtor calls the current classes constructor taking a name 
protected Dog():this("Dog") 
{ 

} 
+0

對於你的最後一個例子,我寧願有一個像'protected Dog(string name =「Dog」)''這樣的構造函數,鏈接的內部構造函數可以相當快地混淆 – Dispersia

+0

@Dispersia我同意,但是缺省值需要在編譯時可用,所以這兩個不是等價的 – konkked

+0

如果他們調用的基礎構造函數,沒有機會能夠傳遞給另一個構造函數除了已經定義的值無論如何 – Dispersia

0

它一直有種這可能是有用的表示,但隨着將參數傳遞給基類型構造函數的能力,此機制還允許選擇哪個構造函數重載調用基類型。