我的最后一个问题是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");
}
}
}
Class 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。
答案 0 :(得分:5)
您正在将构造函数的概念与虚拟方法的概念混合在一起。确实按照从base到derived的顺序调用构造函数,但是你创建了非构造函数的虚方法。
这将提供您想要的输出:
// In Vehicle4Wheels
public Vehicle4Wheels()
{
Console.WriteLine("Vehicle4Wheels constructor");
}
// In SportCar
public SportCar()
{
Console.WriteLine("SportCar constructor");
}
(另外,编辑您在Display()
方法中打印的字符串,因为它们具有误导性 - Display()
不是构造函数。)
对于虚方法(注意abstract
方法自动变为虚方法),“最派生”类方法是被调用的方法,只调用该方法 - 除非方法调用{{1 }}
答案 1 :(得分:1)
这是我得到的输出:Honda Civic Derived222类 构造函数。 Derived111类构造函数。
这是我想要实现的输出:Honda Civic Derived111 class构造函数。 Derived222类构造函数。
好的,只需拨打电话:
public new void Display()
{
base.Display();
Console.WriteLine("Derived222 class Constructor.");
}
答案 2 :(得分:0)
您首先获得Honda Civic,因为它是在创建基类期间输出的。基类的构造函数是在继承类的构造函数中执行的第一件事。
然后你得到Derived222,因为它首先在你的显示方法中输出。
答案 3 :(得分: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
关键字; - )
答案 4 :(得分:0)
您没有显示用于测试课程的代码,但我认为它是这样的:
SportCar car = new SportCar();
car.Display();
第一件不太清楚的是为什么你在抽象类的构造函数中在控制台上编写,但是在派生类的方法中。这意味着,除了消息的顺序之外,只要您创建每个classe的实例,就会编写Honda Civic,而只有在调用Display方法时才会编写其他消息(即使您在编写构造函数时也是如此)方法)。
如果你想在类层次结构的构造函数中做特定的事情,@ Seb给你正确的方法,但是如果你真的想要编写方法Display的不同版本,你必须小心使用覆盖和新的。如果方法是虚方法或抽象方法,则应始终使用override,并将new用于要隐藏基类中定义的方法的情况。你可以在这里找到一个例子(使用像你这样的汽车:-)):[http://msdn.microsoft.com/en-us/library/ms173153(v=vs.80).aspx]。
如果使用override,则正在执行的方法在运行时确定,并取决于对象的类型。如果使用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.
使用覆盖替换new,可以获得您可能期望的内容:
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.