为什么在 C# 中开发了方法隐藏和方法覆盖?我不是在问他们的实施。我特别问的是发明者希望用语言创造这两种东西的场景。为什么方法隐藏在不同的场景中有用(代码示例)以及为什么没有。为什么方法覆盖在某些情况下效果很好,为什么在其他情况下效果不好。实际示例将不胜感激。请注意,我不是要求实施。
1 回答
你问为什么?“为什么”很简单:允许类/对象的多态性。
假设您要创建一个代表汽车的类,另一个代表卡车的类。你可能会注意到,两者都有很多共同的属性(比如它们有轮子、引擎、重量、长度等)和方法(比如说“打开”和“关闭”引擎,增加/减少加速度等)。
你做什么工作?你会用完全相同的代码编写 2 个类,然后只为卡车添加 Weagon 吗?
不,您编写了一个“汽车”类,其中包含汽车的所有方法和属性,以及您制作的一些属性然后“可覆盖”(取决于如何做到这一点的语言 - 我是 C# 程序员所以会是“抽象的”或“虚拟的”,视情况而定)。
然后“卡车”将覆盖最大速度,或站点,或者说它在前部和车上有多少个轮子,如果它之间有一个轴等等。
另一方面,隐藏方法是当基本方法不能被覆盖时(因为,取决于语言,如果不是“使”可覆盖,它就不能被覆盖)等等,在孩子上声明一个方法类,它“隐藏”了原来的类。
它是怎么发生的?假设 Car 类是这样的:
public class Car
{
private double mLength;
private int mMaxSpeed;
public virtual double Length { get { return this.mLength; } set { if (value > 0) { this.mLength = value; } } }
public int MaxSpeed { get { return this.mMaxSpeed; } set { if (value > 0 && value < 350) { this.mMaxSpeed = value; } } }
}
现在,在 C# 上,“virtual”关键字表示方法(或本例中的属性)可以被覆盖,因此缺少它意味着它不能。该类允许覆盖“Length”属性,但不能覆盖“MaxSpeed”。
所以,当我写卡车类时,会是这样的:
public class Truck : Car
{
public override double Length { get { return base.Length; } set { if (value > 20.00) { base.Length = value; } } }
public new int MaxSpeed { get { return base.MaxSpeed; } set { if (value < 100 && value > 0) { base.MaxSpeed = value; } } }
}
通过这样做,Truck 类将覆盖“Length”,但隐藏“MaxSpeed”。由于 Truck 继承(多态性)Car,它可以作为值传递给 Car 的任何变量,所以:
Car m1 = new Car();
Car m2 = new Truck();
这行得通,因为卡车(在我们的定义中)是一辆汽车。那么,后果是什么?如果我创建了一个具有 Car 类型参数的方法,并且我传递了一个 Truck 实例,则被覆盖的方法将(始终)调用它的最高实现,但隐藏的方法将调用特定类型的方法.
所以这:
public static void Initialize(Car vehicle)
{
vehicle.Length = 5.00; //if vehicle is a Car (not derivated) will be 5 if it's a truck will not set
vehicle.MaxSpeed = 350; //will set to 350 for both, even if Truck does not allow over 100, the method called is on the car Class, not Truck
}
Initialize(new Car());
Initialize(new Truck()); //Length won't pass (as intended on Truck class to only allow higher than 20) but MaxSpeed will pass as 350, even if Truck does not allow it
对于隐藏方法 (MaxSpeed) 将是一个问题,但对于覆盖方法 (Length) 则不是。由于 Length 将为其最高实现(它是在卡车上重写的虚拟方法)提供,因此它将始终按照实际类的意图工作,但 MaxSpeed 将使用 Car 类中的方法写入,即使它是卡车也是如此。如果函数/方法使用 Truck 作为参数,它只会在 Truck 类上按预期进行。