为什么要通过其继承的抽象类而不是它自己的类来声明对象

本文关键字:自己的 它自己 对象 声明 继承 抽象类 为什么 | 更新日期: 2023-09-27 18:32:10

public abstract class Character
{
    protected Weapon weapon;
    public string Name;
    public int Health = 10;
    public int Strength;
    public Character()
    {
    }
    public void Attack()
    {
        weapon.useweapon();
    }
}
public class Warrior : Character
{
    public Warrior()
    {
        weapon = new Sword();
        Health = 10;
        Strength = 25;
    }
    public void SetWeapon(Weapon newweapon)
    {
        weapon = newweapon;
    }
}
public class Wizard : Character
{
    public Wizard()
    {
        weapon = new Spell();
        Health = 15;
        Strength = 10;
    }
}

如您所见,有一个抽象的字符类和两个字符子类。在这个程序中,只有战士可以改变武器。现在,我不想讨论代码本身,我想知道的是,在我的实现代码中,我为什么要使用它:

Character Zizo = new Warrior();
Character Hang = new Wizard();

而不是-

Warrior Zizo = new Warrior();
Wizard Hang = new Wizard();
Zizo.SetWeapon(new Axe()); //I can only use this method in this implementation

两者之间有什么区别,通过抽象类声明对象有什么好处?

为什么要通过其继承的抽象类而不是它自己的类来声明对象

客户端代码应使用最低要求的接口或抽象类定义。这样做主要是为了使代码更加松散耦合。在您的示例中,如果调用代码只需要Attack()但不关心如何执行、实现或特定类型(例如 WarriorWizard等)正在进行攻击,那么它应该使用abstract Character类。

当它必须具有特定实现或具体类的知识时,那么显式使用一个是合适的。

您获得的是编写代码的能力,这些代码可以与任何字符类型上的任何公开Character类型成员进行交互,而不管它是什么。

前任:

public void AttackAndHeal(Character character)
{
    character.Attack();
    character.Health++;
}

Warrior zizo = new Warrior();
Wizard hang = new Wizard();
AttackAndHeal(zizo);
AttackAndHeal(hang);

如果你总是知道你会像那样使用它们,那就没有必要了。但通常,您希望抽象出字符的类型,只执行所有字符所暗示的动作。

让我们假设有人在屏幕中间投下了一枚 H 炸弹。你不会在乎你的角色是巫师还是战士(),他们都会是死亡,所以你只需要调用杀戮或任何你拥有的方法。

您可以拥有 Warrior 的泛型集合,并Wizard并重用 Character 类的任何成员

var characters = new List<Character>();
characters.Add(new Warrior());
characters.Add(new Wizard());
foreach (var c in characters)
{
    //use members exposed by c
}

通过将Zizo声明为 Character ,您现在可以将任何类型的Character对象分配给Zizo。 不幸的是,这也将限制您只能调用为 Character 显式声明的属性和函数。 为了调用特定于Warrior Zizo的任何内容,您需要先投射它。

如果在基类和子类上具有同名的常规方法(即未覆盖),则键入对象的变量作为基类将导致在调用该方法时选择基类上的方法。如果您正在寻找该行为,这可能是将其键入为字符的原因。如果您将战士添加到列表中或将其传递给需要字符作为参数的方法,那么它会自动转换为字符(我认为),因此将战士键入为字符可能会使代码不那么容易出错,如果您只是要将其添加到列表或执行任何其他需要字符类型的事情。

相关文章: