类的继承
- 继承的本质:派生类在基类已有的成员的基础之上,对基类进行横向和纵向上的扩展。 横向扩展指的是对类成员个数的扩充,纵向扩展指的是对类成员版本的更新或是对类成员的重写。
- 类在功能上的扩展(extend)
- 只能有一个基类,但可以实现多个其接口
- 类访问级别对继承的影响
- sealed类不能被继承
例:
class Program
{
static void Main(string[] args)
{
Type t = typeof(Car);
Type tb = t.BaseType;
Console.WriteLine(tb.FullName);
//输出为HelloOOP.Vehicle,证明Car是从Vehicle派生出来的
}
}
class Vehicle//作为基类使用
{
}
class Car : Vehicle //构成继承关系
{
}
是一个( is a ):一个子类的实例从语义上来讲,也是父类的一个实例;或者说,一个派生类的实例从语义上来讲,也是基类的一个实例。
class Program
{
static void Main(string[] args)
{
Car car = new Car();
Console.WriteLine(car is Vehicle);
//输出为True
Vehicle vehicle = new Vehicle();
Console.WriteLine(vehicle is Car);
//输出为False
}
}
class Vehicle
{
}
class Car : Vehicle
{
}
一个父类类型的变量,可以引用一个子类类型的实例。
class Program
{
static void Main(string[] args)
{
Vehicle vehicle = new Car();
Object o1 = new Vehicle();
Object o2 = new Car();
}
}
class Vehicle
{
}
class Car : Vehicle
{
}
子类的访问级别不能超越父类的访问级别,可以持平,或者比父类的访问级别更低。
public class Vehicle
{
}
internal class Car : Vehicle
{
}
//Vehicle为internal,Car为public会报错
成员的继承与访问
- 派生类对基类的成员获得与访问
- 在派生类中访问基类的成员
- 构造器的不可继承
class Program
{
static void Main(string[] args)
{
Car car = new Car("Tfos");
Console.WriteLine(car.Owner);
}
}
class Vehicle
{
public Vehicle(string owner) //父类声明构造器
{
this.Owner = owner;
}
public string Owner { get; set; }
}
class Car : Vehicle
{
//方法一:
public Car() : base("N/a") //子类声明构造器;base关键字只能向上访问一层
//当调用父类构造器时,把值"N/A传到构造器里,满足父类构造器的签名
{
this.Owner = "Car Owner";
}
//方法二:
public Car(string owner) :base(owner)
//子类也添加一个参数,把参数传给base构造器
{
this.Owner = owner;
}
//实际使用时只用一个方法
//实例构造器不被继承。如果父类构造器可以被继承,Car就相当于直接有接受参数的构造器,也就不需要再声明一个了
public void ShowOwner()
{
Console.WriteLine(Owner);
}
}
完整实例过程
在项目中添加新的类库:右键Solution,创建MyLib
创建HelloAccess对类库的依赖:右键References,Add Reference,选中MyLib,OK
using System;
namespace MyLib
{
public class Vehicle
{
protected int _rpm;
private int _fuel; //私有字段的访问限制在Vehicle类体里,不能直接访问
public void Refuel()
{
_fuel = 100;
}
protected void Burn(int fuel) //既不想把这个方法暴露给外界引发错误调用,又需要被子类访问
{
_fuel-= fuel;
}
public void Accelerate()
{
Burn(1);
_rpm += 1000;
//每次烧1个油,rpm加1000
}
public int Speed { get { return _rpm / 100; } }
public int Oil { get { return _fuel; } }
}
public class Car : Vehicle
{
public void TurboAccelerate()
{
Burn(2);
_rpm += 3000;
//每次烧2个油,rpm加3000
}
}
}
using System;
using MyLib;
namespace HelloAccess
{
class Program
{
static void Main(string[] args)
{
Car car = new Car();
car.Refuel(); //汽车加油
car.TurboAccelerate(); //汽车加速
Console.WriteLine(car.Speed); //当前速度
Console.WriteLine(car.Oil); //剩余油量
Bus bus = new Bus();
bus.Refuel();
bus.SlowAccelerate();
Console.WriteLine(bus.Speed);
}
}
class Bus : Vehicle
{
public void SlowAccelerate()
{
Burn(1);
_rpm += 500;
}
}
}