有没有办法在运行时接受未知类型?

Is there a way to accept unknown types in runtime?

我正在尝试解决一个简单的 OOP 问题。当我必须创建一些武器并且每个武器都有一个主要动作并且可以通过单击鼠标来执行该主要动作时。例如,霰弹枪正在射击,武士刀正在挥舞。在我的 class 下面是。

public interface IShootable
{
    void TakeShot();
}
public interface ISwingable
{
    void Swing ();
}

public class ShotGun : IShootable
{
    public void TakeShot()
    {
    }
}
public class Kanata : ISwingable
{
    public void Swing ()
    {
    }
}   

每种武器都为其主要动作实现了不同的界面。 (我不确定我是否可以创建一个抽象class,从中我可以继承这些具体的classes。这似乎不能替代两种不同类型的武器。)

我想要实现的是在运行时当用户选择其中一种武器时,用户在鼠标点击时获得正确的操作。对于霰弹枪,它是 TakeShot(),对于武士刀,它是 Swing()

我要做的就是采纳它。或者我应该以其他方式重组 classes。

两者 类 都可以实现第三个接口 - IWeapon,使用 Attack/Use 方法:

public interface IWeapon {
    void Attack();
}

public class ShotGun : IShootable
{
    void IWeapon.Attack() {
        TakeShot();
    }

    public void TakeShot()
    {
    }
}
public class Kanata : ISwingable
{
    public void Swing ()
    {
    }

    void IWeapon.Attack() {
        Swing();
    }
}  

请注意,我这里有 explicitly implemented IWeapon 界面。您不必明确地执行此操作,并且仍然可以在 "normal way" 后执行此操作。但我更喜欢这样。这样,当您有一个 Katana 对象时,只有 Swing 可见,而不是 Attack。我只是觉得让这两种方法都可见是令人困惑的。

另请注意,IWeaponISwingableIShootable无关,因为可摆动的东西(网球拍)和可射击的东西(水枪)不一定是武器。

您可能想做一些更通用的事情:

public interface IWeaponPrimaryAction
{
    void PerformPrimaryAction();
}
public interface IWeaponAction
{
    void PrimaryAction();
}

public class Shoot :IWeaponAction
{
    public void PrimaryAction()
    {
        //Fire in the hole
    }
}   
public class Swing :IWeaponAction
{
    public void PrimaryAction()
    {
        //Into pieces
    }
}
public class ShotGun : IWeaponPrimaryAction
{
    private IWeaponAction _action = new Shoot();
    public void PerformPrimaryAction()
    {
        _action.PrimaryAction();
    }
}
public class Kanata : IWeaponPrimaryAction
{
    private IWeaponAction _action = new Swing();
    public void PerformPrimaryAction()
    {
        _action.PrimaryAction();
    }
}

比注入动作更好:

public class ShotGun : IWeaponPrimaryAction
{
    private IWeaponAction _action;
    public ShotGun(IWeaponAction action)
    {
        _action = action;
    }
    public void PerformPrimaryAction()
    {
        _action.PrimaryAction();
    }
}

我的偏好是@Riki 的建议,并创建一个所有武器都继承 IWeapon 的界面,使用单一方法 IWeapon.PerformPrimaryAction()。但是,如果您不喜欢这样,您可以创建一个所有武器接口都派生自的 "base" 接口,然后在运行时使用转换,isas 来确定您拥有哪种武器:

public interface IWeapon {};

public interface IShootable : IWeapon
{
    void TakeShot();
}

public interface ISwingable : IWeapon
{
    void Swing ();
}

public partial class YourGameClass
{
    public void DoTheAction (IWeapon weapon)
    {
        if (weapon is IShootable)
            (weapon as IShootable).TakeShot();
        if (weapon is ISwingable)
            (weapon as ISwingable).Swing();
    }
}