C#Polymorphism - 指定继承类型

时间:2018-01-11 23:19:53

标签: c# generics inheritance unity3d

我已经在C#中编程了大约六年了,而且我总是试图学习这种语言提供的更多功能,所以我很好奇是否有可能指定一个继承的类来实现排序类似委托的行为,但是使用整个对象而不是单个方法。

我使用带有Buff / Debuff系统的C#在Unity中制作RPG游戏。所有不同的Buffs / Debuff都继承自Aura基类。应用Auras的角色能力继承自基础AuraAbility类,而AuraAbility类继承自基础Ability类。以下是一些相关的上下文代码。

public abstract class Ability
{
    public string Name;
    public float PowerCoefficient;
    public float CastTime;

    public float Cooldown;
    public float CooldownRemaining;

    public Entity Owner;
    public Entity Target;

    public Ability(Entity owner = null)
    {
        Owner = owner;
    }

    protected virtual void Do()
    {
        CooldownRemaining = Cooldown
    }

    /* Other Methods */
}

public class AuraAbility : Ability
{
    /*
     * This would be whatever the delegate-like object would be
     */
    public Aura SpecifiedAura;

    public AuraAbility(Entity owner = null)
        : base(owner)
    {
        // Overridden constructor functionality
    }

    protected override Do()
    {
        /*
         * This is where I want to construct the specified Aura type
         * This isn't real code but just an example of what I want
         */
        Target.AddAura(new SpecifiedAura(Target, Owner));

        base.Do();
    }
}

public class Attune : AuraAbility
{
    public Attune(Entity owner = null)
        : base(owner)
    {
        Name = "Attune";

        CastTime = 0f;
        Cooldown = 4.0f;

        /*
         * Not real code - but this is where I would specify which inherited aura type I wanted
         */
        SpecifiedAura = AttuneBuff;
    }
}

public abstract class Aura
{
    public Raider Owner;
    public Entity Applier;

    public float Duration;
    protected float DurationRemaining;

    public Aura(Entity owner, Entity applier = null)
    {
        Applier = applier;
        Owner = owner;
    }

    /* Other Methods */
}

public class AttuneBuff : Aura
{
     public AttuneBuff(Entity owner, Entity applier = null)
         : base(owner, applier)
     {
         // Overridden constructor functionality
     }

     /* Overridden Methods */
}

现在我想知道是否有办法指定哪个继承的Aura类型我想要AuraAbility.Do()来构造和添加。类似于在定义回调时如何指定委托方法,我想指定一个"委托对象类型"但我不确定正确的术语是什么,或者这种功能是否存在。

我的后备解决方案是覆盖Attune中的Do()来构造和添加AttuneBuff。我认为这是最直接的解决方案,但我不想这样做,因为它需要不必要地重写Do()和复制代码。

另一种解决方案是使AuraAbility成为通用的,如public class AuraAbility<T> where T : Aura。并且有能力继承像public class Attune : AuraAbility<AttuneBuff>。并使用Activator在AuraAbility.Do()中构造泛型类型。

由于我已经有了解决方案,我主要是出于好奇和学习的缘故,因为我不确定这种类型的功能被调用或是否存在。

3 个答案:

答案 0 :(得分:2)

如果您的唯一目标是能够实现未知类型

config: {
  validate: {
      payload : {
          var_a: Joi.string(),
          var_b: Joi.number(),
          var_c Joi.string(),
          var_d: Joi.string(), //IMEI
          var_e: Joi.string(),
          var_f: Joi.string(),
          DONT WANT TO ENTER: Joi.array().items(Joi.number()),
          var_g: random_schema
    }
  }
}

我可以考虑将public Aura SpecifiedAura; // ... Target.AddAura(new SpecifiedAura(Target, Owner)); 替换为{public Aura SpecifiedAura;类型为TargetTTarget类型为Owner

TOwner

这样你就可以:

public Func<TTarget, TOwner, Aura> SpecifiedAuraFunc;

您可以将其定义为:

Target.AddAura(SpecifiedAuraFunc(Target, Owner));

如果你不想仅仅想要一种未知的类型,我现在不知道

答案 1 :(得分:2)

你可以做你想做的事。

public abstract class Ability
{
    public Entity Owner;
    public Entity Target;

    public Ability(Entity owner = null)
    {
        Owner = owner;
    }

    protected abstract void Do();

    /* Other Methods */
}

public abstract class AuraAbility : Ability
{
    private readonly Func<Entity, Entity, Aura> auraFactory;

    protected AuraAbility(Entity owner, 
        Func<Entity, Entity, Aura> auraFactory) 
        : base(owner)
    {
        this.auraFactory = auraFactory;
    }

    protected override void Do()
    {
        Target.AddAura(auraFactory(Owner, Target));
    }
}

public class Attune : AuraAbility
{
    public Attune(Entity owner = null)
        : base(owner, (o, target) => new SpecifiedAura(o, target))
    {
    }
}

请注意,您的计划的某些(许多)方面将受益于重要的代码审查。我建议在代码审查堆栈交换上发帖。

答案 2 :(得分:0)

我会使AuraAbility抽象,然后使用某种方法创建Aura类型,例如abstract Aura CreateAura(Entity owner, Entity applier = null)

这将在BuffAura中被覆盖,如此:

  

受保护的覆盖Aura CreateAura(实体所有者,实体申请人= null)=&gt;新BuffAura(所有者,申请人);