在 C# 中,可以借助_继承_来定义_类_的层次结构,让派生类(Car)继承父类(Vehicle)的行为和数据。如果没有指定父类,该类就会继承object类。
父类可以通过三种方式为派生类提供功能:
virtual方法,它和普通方法类似,只不过是派生类_可以_修改的方法。abstract方法,这种方法没有实现,派生类_必须_实现它。含有abstract方法的类也必须标记为abstract。抽象类不能被实例化。protected访问修饰符允许在派生类中访问父类的成员,但会阻止其他类访问。
派生类可以通过base关键字访问父类的成员。
// Inherits from the 'object' class
abstract class Vehicle
{
// Can be overridden
public virtual void Drive()
{
}
// Must be overridden
protected abstract int Speed();
}
class Car : Vehicle
{
public override void Drive()
{
// Override virtual method
// Call parent implementation
base.Drive();
}
protected override int Speed()
{
// Implement abstract method
}
}
派生类的构造函数会在执行自身构造函数的逻辑_之前_,自动调用父类的构造函数。可以使用base关键字把实参传给父类的构造函数:
abstract class Vehicle
{
protected Vehicle(int wheels)
{
Console.WriteLine("Called first");
}
}
class Car : Vehicle
{
public Car() : base(4)
{
Console.WriteLine("Called second");
}
}
如果有多个类派生自同一个基类,这两个(或更多)类往往会以不同的方式实现基类的同一个方法。这是一个非常重要的原则,叫做多态。例如,在上面例子的一个变体中,我们展示了使用Vehicle的代码如何根据实例化的是哪种载具而改变自己的行为。
abstract class Vehicle
{
public abstract string GetDescription();
}
class Car : Vehicle
{
public Car()
{
}
public override string GetDescription()
{
return "Runabout";
}
}
class Rig : Vehicle
{
public Rig()
{
}
public override string GetDescription()
{
return "Big Rig";
}
}
Vehicle v1 = new Car();
Vehicle v2 = new Rig();
v1.GetDescription();
// => Runabout
v2.GetDescription();
// => Big Rig
在这个练习中,你要玩一款名为“Wizard and Warriors”的角色扮演游戏,可以扮演巫师,也可以扮演战士。
战士和巫师造成多少伤害点数,各有各的规则。
战士的规则如下:
巫师的规则如下:
一般来说,角色永远不会脆弱。不过,巫师如果还没有准备法术,就_是_脆弱的。
你有六个任务,需要用到战士和巫师角色。
重写 Character 类上的 ToString() 方法,返回角色的描述,格式为 "Character is a <CHARACTER_TYPE>"。
var warrior = new Warrior();
warrior.ToString();
// => "Character is a Warrior"
确保 Character.Vulnerable() 方法始终返回 false。
var warrior = new Warrior();
warrior.Vulnerable();
// => false
实现 Wizard.PrepareSpell() 方法,让巫师能够事先准备法术。
var wizard = new Wizard();
wizard.PrepareSpell();
确保巫师没有准备法术时,Vulnerable() 方法返回 true;否则返回 false。
var wizard = new Wizard();
wizard.Vulnerable();
// => true
实现 Wizard.DamagePoints() 方法,返回造成的伤害点数:准备过法术时是 12 点伤害,没有准备时是 3 点伤害。
var wizard = new Wizard();
var warrior = new Warrior();
wizard.PrepareSpell();
wizard.DamagePoints(warrior);
// => 12
实现 Warrior.DamagePoints() 方法,返回造成的伤害点数:目标脆弱时是 10 点伤害,否则是 6 点伤害。
var warrior = new Warrior();
var wizard = new Wizard();
warrior.DamagePoints(wizard);
// => 10