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

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

问题描述

我陷入了以下情况:

  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 可能需要一个 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天全站免登陆