2011-10-03 72 views
2

我最後的問題是在C#中繼承。我以爲我理解這個話題,但不知何故,我忽略了爲什麼輸出是這樣的。控制檯中派生類的順序

這裏是我的類:

BaseClass的:

public abstract class Vehicle 
{ 
    public Vehicle() 
    { 
     Console.WriteLine("Honda Civic"); 
    } 

    public abstract void Display(); 

} 

派生類1:

public class Vehicle4Wheels : Vehicle 
{ 
    public override void Display() 
    { 
     Console.WriteLine("Derived111 class Constructor."); 
    } 
} 

派生類2:

public class SportCar : Vehicle4Wheels 
{ 
    public new void Display() 
    { 
     Console.WriteLine("Derived222 class Constructor."); 
     base.Display(); 
    } 
} 

這是層次結構:基類 - >派生1級 - >派生類2

這是我得到的輸出:

Honda Civic 
Derived222 class Constructor. 
Derived111 class Constructor. 

這是我想達到的輸出:

Honda Civic 
Derived111 class Constructor. 
Derived222 class Constructor. 

我看了幾篇文章的地方有人說,首先打印基類,其他派生類是根據它們在層次結構中的位置打印的。

那麼爲什麼最後一個派生類在第一個派生類之前打印呢?我錯過了什麼(除了C#編程技巧)?

謝謝你的答案。

編輯:

我很抱歉,我花了一段時間才能回到這個主題。更精確地說,我會發布的功課,我想實現的任務:

Work 2: 
An abstract class is not a complete class, it misses some parts, and you cannot create  
objects from it. The programmer who writes the derived classes must fill in the missing 
parts. Consider an abstract class Vehicle. Derive two hierarchies from this class as it 
is shown below: Now, write 4 classes, see the yellow rectangle. Start from the abstract 
base class Vehicle -> Vehicle with 4 wheels -> Sport Cars and stop at the derived class Rally, which is the most specific 
class. The class Vehicle contains a field which holds the vehicle name and an abstract 
method void Display(). 

Implement this function in the derived classes, so that the function returns 
information about the vehicle, e.g. the motor power and other necessary properties. The 
last derived class has private fields to hold the motor power, the car weight, the car 
acceleration, the highest speed and a function that computes the specific power (power 
/weight). The function Display returns a text string with all this information. Test 
your work in a Console application that uses objects of the type of the classes Sport 
car and Rally. 

類車輛:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace A_work_2 
{ 
public abstract class Vehicle 
{ 
    public string vehicleName; 
    public abstract void Display(); 

} 
} 

類Vehicle4Wheels:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace A_work_2 
{ 
public class Vehicle4Wheels : Vehicle 
{ 
    public override void Display() 
    { 
     Console.WriteLine("Car1"); 
    } 
} 
} 

類SportCar:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace A_work_2 
{ 
public class SportCar : Vehicle4Wheels { 
    public override void Display() 
    { 
     Console.WriteLine("Derived222 class Constructor."); 
    } 
} 
} 

類拉力賽:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace A_work_2 
{ 
public class Rally : SportCar 
{ 
    private double motorPower = 408; 
    private double carWeight = 2380; 
    private double carAcceleration = 4.7; 
    private double highestSpeed = 250; 

    public double SpecificPower() 
    { 
     double specificPower = motorPower/carWeight; 
     return specificPower; 
    } 

    public override void Display() 
    { 

     Console.WriteLine("The acceleration is: {0}.\nThe highest speed is {1} km/h.", carAcceleration, highestSpeed); 
     Console.WriteLine("Specific power is {0}", SpecificPower()); 


    } 
} 
} 

我不知道如何用抽象方法實現任務的目標。 謝謝您的回答,V.

+2

您還沒有顯示Vehicle4Wheels ...您已經顯示Vehicle兩次。你的代碼也會*打印*它在構造函數中,而不是來自* actual *構造函數。如果你能想出一個更明智,更完整的例子,那麼幫助你會更容易。 –

+1

編輯你的問題,你錯過了class2的實施 – Boomer

+1

@Boom:請不要使用Leet on SO – abatishchev

回答

0

您首先獲得本田思域,因爲它是在創建基類期間輸出的。基類的構造函數是在繼承類的構造函數中執行的第一件事。

然後你得到Derived222,因爲它是在你的顯示方法中首先輸出的。

1

這是我得到的輸出:Honda Civic Derived222 class 構造函數。 Derived111類構造函數。

這是我試圖實現的輸出:Honda Civic Derived111 class Constructor。 Derived222類構造函數。

好吧,只是交換了電話:

public new void Display() 
    { 
     base.Display(); 
     Console.WriteLine("Derived222 class Constructor."); 
    } 
5

您有虛方法的概念混合構造的概念。構造函數的確按順序從基礎到派生,但是你已經創建了非構造函數的虛擬方法。

這會給你想要的輸出:

// In Vehicle4Wheels 
public Vehicle4Wheels() 
{ 
    Console.WriteLine("Vehicle4Wheels constructor"); 
} 

// In SportCar 
public SportCar() 
{ 
    Console.WriteLine("SportCar constructor"); 
} 

(。此外,編輯你在Display()方式打印字符串,因爲它們是誤導 - Display()構造)

至於虛擬方法(注意abstract方法自動變爲虛擬),「最派生」類的方法是被調用的方法,只有該方法被調用 - 除非該方法調用base.MethodName()

+0

感謝您的回答。我編輯了我的問題。 – Vojtech

0

更改代碼的方式:

public abstract class Vehicle { 
    public Vehicle() { Console.WriteLine("Honda Civic"); } 
} 

public class Vehicle4Wheels : Vehicle { 
    public Vehicle4Wheels() { Console.WriteLine("Derived111 class Constructor."); } 
} 

public class SportCar : Vehicle4Wheels { 
    public SportCar() { Console.WriteLine("Derived222 class Constructor."); 
} 

你不需要重寫Display()方法在你(重新努力實現

並提防使用new關鍵字時的。聲明的方法;-)

0

你沒有告訴你正在使用,以測試你的類的代碼,但我認爲這是這樣的:

SportCar car = new SportCar(); 
car.Display(); 

不清楚的第一件事是爲什麼你要在控制檯上寫抽象類的構造函數,但是在派生類的構造函數中。這意味着,除了消息順序之外,只要您創建了每個類的實例,本田思域就會被編寫,而其他消息僅在您調用Display方法時編寫(即使您將構造函數寫入方法)。

@Seb爲您提供了正確的路徑,如果您想在類的層次結構的構造函數中執行特定的操作,但是如果您真的想編寫方法Display的不同版本,則必須小心使用重寫和新的。如果一個方法是虛擬的或抽象的,你應該總是使用覆蓋,並且在你想要隱藏基類中定義的方法的情況下使用new。你可以在這裏找到一個例子(使用像你這樣的汽車:-)):[http://msdn.microsoft.com/en-us/library/ms173153(v=vs.80).aspx]。

如果使用覆蓋,正在執行的方法在運行時確定並取決於對象的類型。如果使用new,則正在執行的方法在編譯時確定,並取決於您將對象分配給的變量的類型。例如,如果你執行這段代碼與你的類:

 Console.WriteLine("This is the constructor"); 
     SportCar car = new SportCar(); 
     Console.WriteLine("This is the first call to display"); 
     car.Display(); 
     Vehicle4Wheels car2 = car; 
     Console.WriteLine("This is the second call to display"); 
     car2.Display(); 

結果是:

This is the constructor 
Honda Civic 
This is the first call to display 
Derived222 class Constructor. 
Derived111 class Constructor. 
This is the second call to display 
Derived111 class Constructor. 

更換新的與覆蓋你得到什麼你可能期待:

This is the constructor 
Honda Civic 
This is the first call to display 
Derived222 class Constructor. 
Derived111 class Constructor. 
This is the second call to display 
Derived222 class Constructor. 
Derived111 class Constructor.