关于c#:如果更具体,覆盖继承属性或创建一个新属性?


Override inherited property or make a new one if more specific?

我有一个weapon类,projectile类和ballistic weapon类继承了weapon类,ballistic projectile类继承了projectile类,weapon类有一个射弹属性,用于获取和设置武器的射弹。

弹道武器继承了这个,但是弹道武器不会只有任何武器它有一个弹道弹丸(不同于激光弹丸,因为它是瞬间撞击,所以没有弹丸速度)

所以如果我选择覆盖武器的属性,设置者可能会导致问题,因为

1
2
3
4
public Projectile weaponprojectile
{
// getter/setter
}

只需要一个普通的抛射体。吸气剂覆盖将工作正常,因为返回一个弹丸仍然返回一个基本的抛射,它有抛射物做的所有事情,然后一些。不过,二传手肯定不太好。不仅仅是任何炮弹都可以作为弹道导弹。

因此,如果我使用覆盖,是确认弹道和静态转换类型的正确方法,还是应该尝试其他方法?

如果我不使用超控,而是制造一个新的二传手,我担心我最终会得到这个武器,它有两个几乎相同的属性,

它的弹丸和它的弹道弹丸,基本上是一个弹丸加上一些其他的东西,真正有一个得到弹道弹丸是毫无意义的。

我刚开始使用继承,所以如果有人能给我一些基本的指导,如果你有一个带有通用变量的抽象类,你继承了这个类和变量,并且有一个更具体的变量类型,你该怎么做。


您可以使用协方差来允许武器属性中的"特殊"射弹,同时仍然保持将武器视为同一层次的一部分的能力:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
interface IProjectile {
    string Name { get; }
}

// Note the `out` keyword below:
interface IWeapon<out TProjectile> where TProjectile : IProjectile {
    TProjectile Projectile { get; }
}

class BallisticMissile : IProjectile {
    public double Speed { get; set; }
    public string Name { get { return"ballistic missile"; } }
}

class BallisticWeapon : IWeapon<BallisticMissile> {
    public BallisticMissile Projectile { get; set; }
}

class LaserBeam : IProjectile {
    public double WaveLength;
    public string Name { get { return"laser beam"; } }
}

class LaserWeapon : IWeapon<LaserBeam> {
    public LaserBeam Projectile { get; set; }
}

class Program {

    static void Main(string[] args) {

        // Manipulate the ballistic weapon in its own specific way:
        var ballisticWeapon = new BallisticWeapon();
        ballisticWeapon.Projectile = new BallisticMissile();
        ballisticWeapon.Projectile.Speed = 2000;

        // Manipulate the laser weapon in its own specific way:
        var laserWeapon = new LaserWeapon();
        laserWeapon.Projectile = new LaserBeam();
        laserWeapon.Projectile.WaveLength = 400;

        // But you can still use both of them as an IWeapon<IProjectile>:
        var weapons = new List<IWeapon<IProjectile>>();
        weapons.Add(ballisticWeapon);
        weapons.Add(laserWeapon);
        foreach (var weapon in weapons)
            Console.WriteLine(weapon.Projectile.Name);

    }

}


您可能需要发布所有涉及的类。如果我理解你,我会认为你在武器类中有一些射击方法(或使用武器投射物的方法)。您可能希望重写该方法。必须检测类型并采取行动不是最佳设计。更好的方法是封装所做的更改(在本例中,代码执行火/攻击/任何操作)和设置器。例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class BalisticWeapon
{
  public BalisticWeapon(){}

  public override BalisticProjectile weaponprojectile
  {
    get { return Base.weaponprojectile; }
    set { Base.Weaponprojectile = value; }
  }

  public override void Fire()
  {
    //Handle special case for Firing BalisticProjectile
  }
}


有很多方法可以设计你想要的东西。如果是我,我可能会利用接口来避免您描述的继承问题。我还可以在运行时加载的XML文件中描述这些不同类型的武器。然而,类似这样的事情会基于您所描述的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
public interface IWeapon
    {
        int WeaponDamage { get; }
    }

    public interface IBalisticWeapon
    {
        int BallisticDamage { get; }
    }

    public interface IProjectile
    {
        int ProjectileDamage { get; }
    }

    public abstract class WeaponBase: IWeapon
    {
        public virtual int WeaponDamage { get { return 100; } }//base damage
    }

    public class Arrow : WeaponBase, IProjectile, IBalisticWeapon
    {
        public override int WeaponDamage { get { return this.BallisticDamage; } }

        public int BallisticDamage { get { return 10; } }

        public int ProjectileDamage { get { return this.BallisticDamage; } }
    }

    public class BattleAxe : WeaponBase
    {
        //this inherits Weapon Damage from WeaponBase
    }

    public class Rock : WeaponBase, IProjectile
    {
        public override int WeaponDamage { get { return this.ProjectileDamage; } }
        public int ProjectileDamage { get { return 10; } }
    }

    class Program
    {
        static WeaponBase GetWeapon()
        {
            return new Arrow();
        }

        static void Main(string[] args)
        {
            int damage = 0;
            IWeapon weapon = GetWeapon();
            if (weapon is IProjectile)
            {
                damage = (weapon as IProjectile).ProjectileDamage;
            }
            else if (weapon is IBalisticWeapon)
            {
                damage = (weapon as IBalisticWeapon).BallisticDamage;
            }
            else
            {
                damage = (weapon as IWeapon).WeaponDamage;
            }
        }
    }