问题描述
我陷入了这种情况:
- 我有一个名为
Ammo的抽象类
,AmmoBox
和Clip
作为孩子。 - 我有一个名为
Weapon
的抽象类,其中Firearm
和近战
作为孩子。 -
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
,并将它与 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)
提前致谢。
推荐答案
否。你的界面说调用者可以传入任何 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.
这篇关于是否可以使用派生参数而不是基础参数覆盖方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!