是否可以使用派生参数而不是基参数来覆盖方法? [英] Is it possible to override a method with a derived parameter instead of a base one?
问题描述
我陷入了以下情况:
- 我有一个名为
Ammo
的抽象类,其中AmmoBox
和Clip
作为子类. - 我有一个名为
Weapon
的抽象类,其中Firearm
和Melee
作为子级. Firearm
是抽象的,ClipWeapon
和ShellWeapon
作为子元素.- 在
Firearm
里面,有一个void Reload(Ammo ammo);
- I have an abstract class called
Ammo
, withAmmoBox
andClip
as children. - I have an abstract class called
Weapon
, withFirearm
andMelee
as children. Firearm
is abstract, withClipWeapon
andShellWeapon
as children.- Inside
Firearm
, there's avoid 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
中删除 Reload
,并将 ClipWeapon
和 ShellWeapon
与特定的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 ...
}
当然我试过了,它没有用,我收到一个错误,说签名必须匹配或其他什么,但这不应该是逻辑上"有效的吗?因为 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'?
没有.您的界面表明调用者可以传入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屋!