Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 用继承的类作为参数重写_C#_Unity3d_Inheritance - Fatal编程技术网

C# 用继承的类作为参数重写

C# 用继承的类作为参数重写,c#,unity3d,inheritance,C#,Unity3d,Inheritance,我正在为我的2D游戏开发一个模块化武器系统,我遇到了以下问题: 假设我有一个名为武器的抽象基类 公共抽象类武器:单一行为 { 公共整数损坏{get;set;} 公共int持久性{get;set;} 公共精灵精灵{get;set;} 公开摘要无效初始化(武器数据武器数据); } 以及继承自武器的手枪类 公共级手枪:武器{ 手枪数据; void Start(){ 初始化(数据); } 公共覆盖无效初始化(PistolData PistolData){ //做点什么 } } 您可以看到这两个类在I

我正在为我的2D游戏开发一个模块化武器系统,我遇到了以下问题:

假设我有一个名为
武器的抽象基类

公共抽象类武器:单一行为
{
公共整数损坏{get;set;}
公共int持久性{get;set;}
公共精灵精灵{get;set;}
公开摘要无效初始化(武器数据武器数据);
}
以及继承自武器的手枪类

公共级手枪:武器{
手枪数据;
void Start(){
初始化(数据);
}
公共覆盖无效初始化(PistolData PistolData){
//做点什么
}
}
您可以看到这两个类在Initialize方法/函数中使用以下两个类。A
武器数据
等级:

公共抽象类武器数据:ScriptableObject
{
公众参与;
公共财产损害;
}
以及继承自武器数据的
手枪数据

[CreateAssetMenu(fileName=“new PistolData”,menuName=“MyAssets/PistolData”,order=0)]
公共类数据:武器数据
{
公共向量2支点;
公共向量2火点;
公共游戏对象公告;
公共安全部队;
公共精灵武器;
公共浮式灭火器;
}
我现在的问题是:我得到一个错误,因为初始化需要一个
武器数据
,而不是
手枪数据
。我认为这是可行的,因为通过继承,
PistolData
实际上是一个
WeaponData
。。至少我这么认为

有没有办法让这种继承成为可能?如果不是,我应该如何解决它


我对Unity和C非常陌生,如果不是这样,我不知道如何管理我的武器系统。

你可以使方法无参数,只需使用字段中的值

public override void Initialize()
{
    // do something with pistolData since you seem to have it as field
}

您还可以添加一个类型检查,如

public class Pistol : Weapon 
{
    [SerializeField] PistolData _pistolData;

    void Start() 
    {
        Initialize(pistolData);
    }

    public override void Initialize(WeaponData weaponData)
    {
        if (!(weaponData is PistolData pistolData))
        {
            Debug.LogError("I expected a " + nameof(PistolData), this);
            return;
        }

        // use pistolData
    }
}

或者,您可以在
武器中实现武器的功能,并在继承的方法中使用非重写方法:

public abstract class Weapon : MonoBehaviour
{
    public int damage { get; private set; }
    public int durablity { get; private set; }
    public Sprite sprite { get; set; }

    protected void Initialize(WeaponData weaponData)
    {
        damage = weapondData.damage;
        durability = weaponData.durability
    }
}
然后

public class Pistol : Weapon
{
    public void Initialize(PistolData pistolData)
    {
        base.Initialize(pistolData);

        // do pistol specific stuff
    }
}

您可以使方法无参数,只需使用字段中的值

public override void Initialize()
{
    // do something with pistolData since you seem to have it as field
}

您还可以添加一个类型检查,如

public class Pistol : Weapon 
{
    [SerializeField] PistolData _pistolData;

    void Start() 
    {
        Initialize(pistolData);
    }

    public override void Initialize(WeaponData weaponData)
    {
        if (!(weaponData is PistolData pistolData))
        {
            Debug.LogError("I expected a " + nameof(PistolData), this);
            return;
        }

        // use pistolData
    }
}

或者,您可以在
武器中实现武器的功能,并在继承的方法中使用非重写方法:

public abstract class Weapon : MonoBehaviour
{
    public int damage { get; private set; }
    public int durablity { get; private set; }
    public Sprite sprite { get; set; }

    protected void Initialize(WeaponData weaponData)
    {
        damage = weapondData.damage;
        durability = weaponData.durability
    }
}
然后

public class Pistol : Weapon
{
    public void Initialize(PistolData pistolData)
    {
        base.Initialize(pistolData);

        // do pistol specific stuff
    }
}

使用泛型和泛型约束应该可以满足您的需要

public abstract class Weapon<TWeaponData> : MonoBehaviour
    where TWeaponData : WeaponData
{
    public int damage { get; set; }
    public int durablity { get; set; }
    public Sprite sprite { get; set; }

    public abstract void Initialize(TWeaponData weaponData);
}
公共抽象类武器:单一行为
TWeaponData在哪里:武器数据
{
公共整数损坏{get;set;}
公共int持久性{get;set;}
公共精灵精灵{get;set;}
公开摘要无效初始化(TWeaponData武器数据);
}
那么你的手枪课可以做到这一点

public class Pistol : Weapon<PistolData>
{
    PistolData pistolData;

    void Start() {
        Initialize(pistolData);
    }

    public override void Initialize(PistolData pistolData) {
       //do something
    }
}
公共级手枪:武器
{
手枪数据;
void Start(){
初始化(数据);
}
公共覆盖无效初始化(PistolData PistolData){
//做点什么
}
}

使用泛型和泛型约束可以满足您的需要

public abstract class Weapon<TWeaponData> : MonoBehaviour
    where TWeaponData : WeaponData
{
    public int damage { get; set; }
    public int durablity { get; set; }
    public Sprite sprite { get; set; }

    public abstract void Initialize(TWeaponData weaponData);
}
公共抽象类武器:单一行为
TWeaponData在哪里:武器数据
{
公共整数损坏{get;set;}
公共int持久性{get;set;}
公共精灵精灵{get;set;}
公开摘要无效初始化(TWeaponData武器数据);
}
那么你的手枪课可以做到这一点

public class Pistol : Weapon<PistolData>
{
    PistolData pistolData;

    void Start() {
        Initialize(pistolData);
    }

    public override void Initialize(PistolData pistolData) {
       //do something
    }
}
公共级手枪:武器
{
手枪数据;
void Start(){
初始化(数据);
}
公共覆盖无效初始化(PistolData PistolData){
//做点什么
}
}

虽然这样可以编译,但这是一个非常糟糕的设计。如果要检查子类中的参数类型,为什么首先要有一个抽象基方法?在很多情况下,您都希望这样做。您是否有更好的设计,然后将其作为备选方案提供;)问题中没有足够的上下文来提供适当的解决方案。但是,您不需要记住要传递给方法的特定子类型,然后在运行时找出任何错误。@Cratus很好,确切地说,这是不可能的,除非您使用我提供的替代方法或搜索其他方法;)如果您
重写
该方法,则您不能更改其签名,因为最后一次
公共无效初始化(PistolData PistolData){base.Initialize(PistolData);}
对我有效,并且不会引发任何错误<代码>手枪数据
是一个
武器数据
,而这将编译它是一个非常糟糕的设计。如果要检查子类中的参数类型,为什么首先要有一个抽象基方法?在很多情况下,您都希望这样做。您是否有更好的设计,然后将其作为备选方案提供;)问题中没有足够的上下文来提供适当的解决方案。但是,您不需要记住要传递给方法的特定子类型,然后在运行时找出任何错误。@Cratus很好,确切地说,这是不可能的,除非您使用我提供的替代方法或搜索其他方法;)如果您
重写
该方法,则您不能更改其签名,因为最后一次
公共无效初始化(PistolData PistolData){base.Initialize(PistolData);}
对我有效,并且不会引发任何错误
PistolData
是一种
WeaponData
您希望通过定义抽象基方法实现什么?如果只通过子类构造函数调用它,那是多余的。@Johnathan Barclay我只调用基类的Initialize()。使用哪个Initialize()取决于我的武器来自哪个子类(例如手枪、剑、斧)。通过定义抽象基方法,您希望实现什么?如果只通过子类构造函数调用它,那是多余的。@Johnathan Barclay我只调用基类的Initialize()。whi