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

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

问题描述

我陷入了以下情况:

  1. 我有一个名为 Ammo 的抽象类,其中 AmmoBoxClip 作为子类.
  2. 我有一个名为 Weapon 的抽象类,其中 FirearmMelee 作为子级.
  3. Firearm 是抽象的,ClipWeaponShellWeapon 作为子元素.
  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 可以同时使用 ClipAmmoBox 重新加载:

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 可能需要 AmmoBoxcode>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 中删除 Reload,并将 ClipWeaponShellWeapon 与特定的params 我需要,但这样做我会失去多态的好处,这不是我想要的.

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 中覆盖 Reload,这不是最佳选择吗:

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

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

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

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?

我该如何解决这个问题?总的来说,我的设计是否正确?(注意我使用接口 IClipWeaponIShellWeapon 但我遇到了麻烦,所以我转而使用类)

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'?

没有.您的界面表明调用者可以传入any 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天全站免登陆