类的继承(重写)
- 类成员的”横向扩展”:成员越来越多(上小节)
- 类成员的”纵向扩展”:行为改变,版本增高(即重写)
- 类成员的隐藏(工作中是需要避免的,不常用)
- 重写与隐藏的发生条件:函数成员(方法/属性),可见(访问级别为public/protected),签名一致
- 重写的函数成员具体可以为以下:
- 示例:子类成员对父类成员的重写,父类成员用virtual修饰,子类成员用override修饰 ```csharp using System;
namespace OverrideExample { class Program { static void Main(string[] args) { Car car = new Car(); car.Run();//输出:Car is running!
Vehicle v = new Vehicle();
v.Run();//I'm running!
Vehicle v1 = new Car();//Is a
v1.Run();//输出:Car is running!
}
}
class Vehicle
{
public virtual void Run()
{
Console.WriteLine("I'm running!");
}
}
class Car : Vehicle
{
public override void Run()
{
Console.WriteLine("Car is running!");
}
}
}
- 如果父类成员不加virtual,子类成员不加override,则表示子类成员对父类成员的隐藏
- 隐藏时Car类中有两个Run方法,一个this的Run,一个base的Run(继承父类的)
- 隐藏时Vehicle v1 = new Car(); v1.Run();输出I'm running!,而重写则Car类中只有一个版本的Run方法
- 示例:继续增加派生类,引申多态概念,父类类型的变量引用子类类型的实例
```csharp
using System;
namespace OverrideExample
{
class Program
{
static void Main(string[] args)
{
Vehicle v = new RaceCar();//多态
v.Run();//输出:RaceCar is running!
}
}
class Vehicle
{
public virtual void Run()
{
Console.WriteLine("I'm running!");
}
}
class Car : Vehicle
{
public override void Run()
{
Console.WriteLine("Car is running!");
}
}
class RaceCar : Car
{
public override void Run()
{
Console.WriteLine("RaceCar is running!");
}
}
}
- 如果RaceCar的Run方法不写override修饰,则RaceCar类中有2个版本的Run方法,一个是自身的,一个是Car版本的
- 当Vehicle v = new RaceCar()时,变量v会顺着继承链向下找到Car时,Run不在向下重写,所以输出的结果为Car is running!,若想输出RaceCar is running!,则需改成RaceCar rc = new RaceCar()
多态
- 基于重写机制(virtual -> override)
- 函数成员的具体行为(版本)由对象决定
- 属性也是method member,所以也能重写
- 示例:属性的重写 ```csharp using System;
namespace OverrideExample { class Program { static void Main(string[] args) { Vehicle v = new Car(); v.Run();//输出:Car is running! Console.WriteLine(v.Speed);///输出:50 } }
class Vehicle
{
private int _speed;
public virtual int Speed
{
get { return _speed; }
set { _speed = value; }
}
public virtual void Run()
{
Console.WriteLine("I'm running!");
_speed = 100;
}
}
class Car : Vehicle
{
private int _rpm;
public override int Speed
{
get { return _rpm / 100; }
set { _rpm = value * 100; }
}
public override void Run()
{
Console.WriteLine("Car is running!");
_rpm = 5000;
}
}
} ```