包含另一个可继承对象的C#继承



我有以下对象

class Magazine 
{ 
    String intendedGunId {get;}//Returns some Gun.weaponID;
    int size {get;}
    //Implementation
}
class Gun 
{
    public enum FireModes
    {
        Bolt,
        Semi,
        FullAuto
    }
    public FireModes fireMode { get; private set; }
    Magazine magazine;
    public Magazine reload(Magazine newMag)
    {
        if (magazine.intendedGunId == newMag.intendedGunID)
        {
            Magazine temp = magazine;
            this.magazine = newMag;
            return temp;
        }
         return newMag;
    }
    //Other implementation
 }
class AKMag : Mag
{
   //Implementation
}
class AK : Gun
{
   //Implementation
}

我正在设计一把枪和一个弹匣,它应该总是用于多支不同的枪。

我不认为将Magazine变量保持为T : Magazine而不仅仅是Magazine是一个明智的想法,因为在重新加载时,几乎任何Magazine都可以被接受,而且它感觉不像是安全的代码;我觉得黑客很容易利用这一点。

我尝试了以下通用:

class Gun<T> where T : Magazine
{
    T magazine;
    //Other implementation
}
class AK : Gun<AKMag>
{
}

问题是,一旦我使用泛型,就不可能存储Gun<Magazine>变量,因为在某个时候,编译器会说"无法从Gun<AKMag>转换为Gun<T> where T : Magazine。"

基本上,每把枪都有自己的弹匣,只属于自己的枪。我很难正确地实现这一点,可能是因为对C#泛型或C#继承缺乏了解。

编辑:对于通用枪,以下场景不起作用:

Gun<Magazine> someGun;
public void func (Gun<Magazine> gun)
{
    this.someGun = gun;
}
//In another class
AK<AKMagazine> someAK;
public void func2 ()
{
    func1 (someAK);  //Error: "Can not convert from `Gun<AKMag>` to `Gun<T> where T : Magazine`."
}

编辑:我决定最好的方法是检查一下杂志。GetType()==newMag.GetType()只要mag要更改,接口也可以工作。

只使用普通的旧接口怎么样?

    class Program
    {
        static void Main(string[] args)
        {
            Gun myGun = new AK();
            Console.WriteLine(myGun.load(new AK_Mag())); // true
            Console.WriteLine(myGun.load(new ShotGun_Mag())); // false
            func2();
        }
        static Gun someGun;
        static void func1(Gun gun)
        {
            someGun = gun; 
        }
        public static void func2()
        {
            Gun someAK = new AK();
            someAK.load(new AK_Mag());
            func1(someAK);
        }
    }
    public class AK : Gun
    {
        public bool load(Mag mag)
        {
            if (mag == null)
                return false;
            if ( mag.GetType() != typeof(AK_Mag))
            {
                return false;
            }
            return true;
        }
        public void shoot(int x, int y, int z)
        {
            throw new NotImplementedException();
        }
        public bool setFireMode(Gun.FireMode mode)
        {
            this.mode = mode;
            return true;
        }
    }
    public class AK_Mag : Mag
    {
        public int Remain()
        {
            throw new NotImplementedException();
        }
    }
    public class ShotGun_Mag : Mag
    {
        public int Remain()
        {
            throw new NotImplementedException();
        }
    }
    public interface Gun
    {
        public enum FireMode { Manual, Burst };
        bool load(Mag mag);
        void shoot(int x, int y, int z);
        bool setFireMode(FireMode mode);        
    }
    public interface Mag
    {
        int Remain();
    }
泛型类型参数的继承不涉及泛型类的继承。我认为泛型不是正确的解决方案。

尝试这种方法:

class Magazine
{
    public readonly Type GunType; // Used for identification of compatible gun type.
    public Magazine (Type gunType)
    {
        this.GunType = gunType;
    }
}
class Gun
{
    // Factory method
    public Magazine CreateMagazine()
    {
        return new Magazine(this.GetType());
    }
    public Magazine Reload(Magazine newMag)
    {
        // Test whether the magazine is compatible with the current gun.
        if (newMag.GunType != this.GetType()) {
            throw new ArgumentException();
            // Or just reject the new magazine and keep the current one.
        }
        // Your reload logic goes here ...
    }
}

泛型的问题是,即使AB之间存在继承关系,T<A>T<B>这两种类型也不能进行赋值兼容。另一个问题是,泛型在编译时得到完全解决。你需要一个更动态的方法。在游戏中,您可能希望将枪支和弹匣存储在用户的库存中,并以相同的方式处理所有枪支和弹仓类型。可以在运行时以完全动态的方式将所需类型存储为System.Type

你可以创建和使用这样的杂志:

Gun gun = new AK();
Magazine magazine = gun.CreateMagazine();
Magazine other = gun.Reload(magazine);

最新更新