3
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 类和两个 Character 子类。在这个程序中,只有战士可以更换武器。现在,我不想讨论代码本身,我想知道的是,在我的实现代码中为什么要使用它:

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

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

4

6 回答 6

4

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

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

于 2012-04-25T18:28:32.920 回答
3

你得到的是编写代码的能力,该代码可以与Character任何字符类型上的任何公开暴露的类型成员进行交互,无论它是什么。

前任:

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

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

AttackAndHeal(zizo);
AttackAndHeal(hang);
于 2012-04-25T18:28:25.433 回答
1

如果你总是知道你会那样使用它们,那就没有必要了。但通常你想抽象出角色的类型,只执行所有角色都执行的动作。

假设有人在屏幕中间投下了一颗 H 炸弹。你不会关心你的角色是 Wizards 还是 Warriors() 他们都会死,所以你只需要调用 Kill 或任何你有的方法。

于 2012-04-25T18:28:43.463 回答
1

您可以拥有一个通用集合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
}
于 2012-04-25T18:28:59.493 回答
0

If you have a regular method (i.e. not overidden) of the same name on the base class and the child class then typing the variable of the object as the base class will cause the method on the base class to be chosen if the method is called. That might be a reason to type it as a character if your looking for that behavior. If you add the warrior to a List or pass it in to a method requiring a Character as a parameter then it's automatically casted to Character (i think), so typing a warrior as Character might make the code less error prone if you are just going to be adding it to list or doing anything else requiring a Character type.

于 2012-10-23T00:42:36.660 回答
0

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

于 2012-04-25T18:29:31.683 回答