轨道
/
C#
C#
/
练习
/
巫师与战士
巫师与战士

巫师与战士

学习练习

简介

继承

在 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”的角色扮演游戏,可以扮演巫师,也可以扮演战士。

战士和巫师造成多少伤害点数,各有各的规则。

战士的规则如下:

  • 如果被攻击的角色不脆弱,造成 6 点伤害
  • 如果被攻击的角色脆弱,造成 10 点伤害

巫师的规则如下:

  • 如果巫师事先准备了法术,造成 12 点伤害
  • 如果巫师没有事先准备法术,造成 3 点伤害

一般来说,角色永远不会脆弱。不过,巫师如果还没有准备法术,就_是_脆弱的。

你有六个任务,需要用到战士和巫师角色。

1. 描述角色

重写 Character 类上的 ToString() 方法,返回角色的描述,格式为 "Character is a <CHARACTER_TYPE>"。

var warrior = new Warrior();
warrior.ToString();
// => "Character is a Warrior"

2. 让角色默认不脆弱

确保 Character.Vulnerable() 方法始终返回 false。

var warrior = new Warrior();
warrior.Vulnerable();
// => false

3. 让巫师能够准备法术

实现 Wizard.PrepareSpell() 方法,让巫师能够事先准备法术。

var wizard = new Wizard();
wizard.PrepareSpell();

4. 让巫师在没有准备法术时变得脆弱

确保巫师没有准备法术时,Vulnerable() 方法返回 true;否则返回 false。

var wizard = new Wizard();
wizard.Vulnerable();
// => true

5. 计算巫师的伤害点数

实现 Wizard.DamagePoints() 方法,返回造成的伤害点数:准备过法术时是 12 点伤害,没有准备时是 3 点伤害。

var wizard = new Wizard();
var warrior = new Warrior();

wizard.PrepareSpell();
wizard.DamagePoints(warrior);
// => 12

6. 计算战士的伤害点数

实现 Warrior.DamagePoints() 方法,返回造成的伤害点数:目标脆弱时是 10 点伤害,否则是 6 点伤害。

var warrior = new Warrior();
var wizard = new Wizard();

warrior.DamagePoints(wizard);
// => 10
通过 GitHub 编辑 链接将在新窗口或新标签页中打开
C# Exercism

准备好开始 巫师与战士 了吗?

注册 Exercism,借助 62 个概念178 个练习 和真人导师指导,学习并掌握 C#,全部免费。