是否可以使用派生参数而不是基础参数覆盖方法? [英] Is it possible to override a method with a derived parameter instead of a base one?

查看:93
本文介绍了是否可以使用派生参数而不是基础参数覆盖方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我陷入了这种情况:


  1. 我有一个名为 Ammo的抽象类 AmmoBox Clip 作为孩子。

  2. 我有一个名为 Weapon 的抽象类,其中 Firearm 近战作为孩子。

  3. Firearm 是抽象的, ClipWeapon ShellWeapon 作为孩子。

  4. 内部 Firearm ,有一个 void Reload(Ammo ammo);

  1. I have an abstract class called Ammo, with AmmoBox and Clip as children.
  2. I have an abstract class called Weapon, with Firearm and Melee as children.
  3. Firearm is abstract, with ClipWeapon and ShellWeapon as children.
  4. Inside Firearm, there's a void Reload(Ammo ammo);

问题是, ClipWeapon 可以使用 Clip AmmoBox 重新加载:

The problem is that, a ClipWeapon could use both a Clip and an AmmoBox to reload:

public override void Reload(Ammo ammo)
{
    if (ammo is Clip)
    {
        SwapClips(ammo as Clip);
    }
    else if (ammo is AmmoBox)
    {
        var ammoBox = ammo as AmmoBox;
        // AddBullets returns how many bullets has left from its parameter
        ammoBox.Set(clip.AddBullets(ammoBox.nBullets));
    }
}

但是 ShellWeapon ,只能使用 AmmoBox 重新加载。我可以这样做:

But a ShellWeapon, could only use an AmmoBox to reload. I could do this:

public override void Reload(Ammo ammo)
{
    if (ammo is AmmoBox)
    {
        // reload...
    }
}

但这很糟糕,因为即使我正在检查以确保它的类型为 AmmoBox ,从外面看,它看起来像 ShellWeapon 也可以带一个 Clip ,因为 Clip Ammo

But this is bad because, even though I'm checking to make sure it's of type AmmoBox, from the outside, it appears like a ShellWeapon could take a Clip as well, since a Clip is Ammo as well.

或者,我可以从中移除重新加载 Firearm ,并将它与 ClipWeapon ShellWeapon 一起放入我需要特定的参数,但这样做我将失去多态性的好处,这不是我想要的。

Or, I could remove Reload from Firearm, and put it both ClipWeapon and ShellWeapon with the specific params I need, but doing so I will lose the benefits of Polymorphism, which is not what I want to.

如果我能覆盖它会不是最优的重新加载 ShellWeapon 内,如下所示:

Wouldn't it be optimal, if I could override Reload inside ShellWeapon like this:

public override void Reload(AmmoBox ammoBox)
{
   // reload ... 
}

当然我试过了,它没有用,我收到一个错误,说签名必须匹配或者其他什么,但这不应该是逻辑有效吗?因为 AmmoBox Ammo

Of course I tried it, and it didn't work, I got an error saying the signature must match or something, but shouldn't this be valid 'logically'? since AmmoBox is a Ammo?

我该怎么办?绕过这个?一般来说,我的设计是否正确?
(注意我使用接口 IClipWeapon IShellWeapon 但我遇到了麻烦,所以我转而使用而不是类)

How should I get around this? And in general, is my design correct? (Note I was using interfaces IClipWeapon and IShellWeapon but I ran into trouble, so I moved to using classes instead)

提前致谢。

推荐答案


但这不应该在逻辑上有效吗?

but shouldn't this be valid 'logically'?

否。你的界面说调用者可以传入任何 Ammo - 你限制它需要 AmmoBox ,更具体。

No. Your interface says that the caller can pass in any Ammo - where you're restricting it to require an AmmoBox, which is more specific.

如果有人写信,你会发生什么:

What would you expect to happen if someone were to write:

Firearm firearm = new ShellWeapon();
firearm.Reload(new Ammo());

?那应该是完全有效的代码 - 所以你想让它在执行时爆炸吗?静态类型的一半是为了避免这种问题。

? That should be entirely valid code - so do you want it to blow up at execution time? Half the point of static typing is to avoid that sort of problem.

可以使 Firearm 使用弹药类型的泛型:

You could make Firearm generic in the type of ammo is uses:

public abstract class Firearm<TAmmo> : Weapon where TAmmo : Ammo
{
    public abstract void Reload(TAmmo ammo);
}

然后:

public class ShellWeapon : Firearm<AmmoBox>

这可能是也可能不是一种有用的做事方式,但至少值得考虑。

That may or may not be a useful way of doing things, but it's at least worth considering.

这篇关于是否可以使用派生参数而不是基础参数覆盖方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆