覆写
派生类可以声明和基类同名的成员。
如果不加修饰符或使用new关键字修饰(只有醒目提醒的作用),则会覆写基类成员。
覆写后如果还想访问基成员,需要使用base关键字访问。
class 英雄
{
public int hp;
public int atk;
}
class 盖伦 : 英雄
{
public new int hp;
public new int atk;
public void Show()
{
Console.WriteLine("自己的atk是" + atk);
Console.WriteLine("基类的atk是" + base.atk);
}
}
在覆写后,派生类会实实在在地存在两个同名成员。
具体会访问到哪一个成员,取决于变量声明的类型。
盖伦 galen = new 盖伦();
英雄 hero = galen;
galen.hp = 12;
hero.hp = 20;
galen.Show();
Console.WriteLine(galen.hp);
Console.WriteLine(hero.hp);
虚成员
属性或方法可以以virtual修饰,这使得他们可以在派生类中被重写。
虚成员不能是私有的,因为他们需要通过继承来发挥功能,私有成员没有访问权限。
class 妙蛙种子
{
public string name;
public int hp;
public 妙蛙种子(string name = "妙蛙种子", int hp = 100)
{
this.name = name;
this.hp = hp;
}
public virtual void 光合作用()
{
hp += 20;
Console.WriteLine(name + "通过光合作用恢复了20生命值");
}
}
重写虚成员
使用override关键字可以重写基类的虚成员(重写过的成员仍然是虚成员)。
生成重写时,不能再声明一个隐藏同名基类成员的成员(重写和覆写只能选一个)。
重写时,不能更改访问修饰符。键入访问修饰符和override后,自动补全会列出相同修饰符的可重写成员。
class 妙蛙草 : 妙蛙种子
{
public 妙蛙草(string name = "妙蛙草", int hp = 150) : base(name, hp)
{
}
public override void 光合作用()
{
hp += 30;
Console.WriteLine(name + "通过光合作用恢复了30生命值");
}
}
class 妙蛙花 : 妙蛙草
{
public 妙蛙花(string name = "妙蛙花", int hp = 250) : base(name, hp)
{
}
public override void 光合作用()
{
hp += 50;
Console.WriteLine(name + "通过光合作用恢复了50生命值");
}
}
重写属性时,不能重写基类没有的访问器。如果派生类没有重写的访问器会继续存在。
调用重写的虚成员
当值是派生类时,就会调用到派生类重写后的虚成员。
哪怕是从基类的方法调用的,哪怕是从基类的构造器里调用的。
植物 a = new 西瓜();
class 植物
{
public 植物() => Show();
public virtual void Show() => Console.WriteLine("这是植物");
}
class 果蔬 : 植物
{
public override void Show() => Console.WriteLine("这是果蔬");
}
class 西瓜 : 果蔬
{
public override void Show() => Console.WriteLine("这是西瓜");
}
访问未重写的成员
在派生类中,依然可以使用base来访问未重写过的基类成员。