重写继承的属性,如果更具体,则创建一个新属性

本文关键字:属性 新属性 一个 创建 继承 如果 重写 | 更新日期: 2023-09-27 18:11:31

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

弹道武器继承了这一点,但弹道武器不会有任何武器它有一个弹道弹丸(不同于激光弹丸,激光弹丸不会有弹丸速度,因为它是即时撞击)

所以如果我选择重写武器的属性,setter可能会导致问题,因为

public Projectile weaponprojectile
{
// getter/setter
}

只需要一个一般的抛射体。getter重写会工作得很好因为返回一个弹道抛射仍然是返回一个基础抛射,它有抛射所做的所有事情。然而setter并不是绝对正确的。并不是所有的弹丸都可以被设定为弹道弹丸。

所以,如果我使用重写是正确的方式来确认类型的弹道和静态转换,还是我应该尝试其他东西?

如果我不使用重写,而是创建一个新的setter,我担心我最终会得到这个有两个几乎相同属性的武器,

它的抛射物和它的弹道抛射物基本上是抛射物加上一些其他的东西,真正拥有一个弹道抛射物是没有意义的。

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

重写继承的属性,如果更具体,则创建一个新属性

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

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);
    }
}

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

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;
            }
        }
    }

您可能需要发布所有涉及的类。如果我理解你的话,我会认为你在Weapon类中有一些Fire方法(或者一些使用武器弹的方法)。你可能想要重写那个方法。必须检测类型并采取行动并不是最好的设计。最好将变化(在本例中是执行Fire/Attack/Whatever的代码)和Setter封装起来。示例

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
  }
}