简体   繁体   English

C#继承多态类型

[英]C# Inheriting polymorphic types

Starting out with a basic class called Weapon, I intended it to be polymorphic as follows: 从一个名为Weapon的基本类开始,我希望它是多态的,如下所示:

public class Weapon
{
    // Some code..
}

public class MachineGun : Weapon
{
    // Extend the base code..
}

These classes define the basic functionality, however they do not contain any code to draw the weapon. 这些类定义了基本功能,但是它们不包含任何用于绘制武器的代码。 This drawing only needs to be added in the Client application, the Server simply uses the MachineGun class without needing visualization. 仅需要在客户端应用程序中添加此图形,服务器仅使用MachineGun类,而无需可视化。

public class DrawableWeapon : Weapon
{
    // Adding draw calls and properties
}

public class DrawableMachineGun : DrawableWeapon
{
    // The problem:
    // You have no access to the properties of the original MachineGun here
}
// or..
public class DrawableMachineGun : MachineGun
{
    // Same problem, only now you miss properties of the DrawableWeapon
}

The problem is losing either functionality of the MachineGun() class or the DrawableWeapon() class, since C# has no multiple inheritance. 问题是失去了MachineGun()类或DrawableWeapon()类的功能,因为C#没有多重继承。

Defining the Weapon class as an interface gave no succes either, you can't define methods in an interface which is exactly what I need to reduce code. 将Weapon类定义为接口也没有成功,也无法在接口中定义方法,而这正是我减少代码所需的。

The only (partial) solution I found was for methods: define them in a seperate static class and on each method call in a drawable class, call this static method as well. 我发现的唯一(部分)解决方案是针对方法的:在单独的静态类中定义它们,并在可绘制类的每个方法调用上也都调用此静态方法。 This still leaves out all properties, and leads to long method calls.. 这仍然会遗漏所有属性,并导致较长的方法调用。

What is the best option to implement this nicely? 完美实现此目标的最佳选择是什么? Is there a better programming pattern to use in this case? 在这种情况下是否有更好的编程模式?

Yes. 是。 You can use a Decorator pattern: 您可以使用装饰器模式:

    public class Weapon
    {
       public virtual void Shot()
       { 
          // Some code...
       }
    }

    public class MachineGun : Weapon
    {
       public override void Shot()
       { 
          // Extend base code...
       }
    }

    public class DrawableWeapon : Weapon
    {
       Weapon mWeapon;

       public override void Shot()
       { 
          mWeapon.Shot();
       }

        // Adding draw calls and properties
    }

You can use decorator pattern to extend your classes without inheritance . 您可以使用装饰器模式扩展类而无需继承 It is good to remember favor object composition over inheritance principle for this kind of polymorphism problems. 对于此类多态性问题,最好记住偏爱对象组成而不是继承原理。

interface Weapon : Weapon {
    void Fire();
}

class MachineGun : Weapon {
    public override void Fire() {
        for (int i = 0; i < 5; i++) {
            // Do something
        }
    }
}

class HandGun : Weapon {
    public override void Fire() {
        // Do something
    }
}

abstract class WeaponDecorator : Weapon {
    protected Weapon weapon;

    public WeaponDecorator(Weapon weapon) {
        this.weapon = weapon;
    }

    // Implement methods by calling this.weapon's method

    public virtual void Fire() {
        weapon.Fire();
    }
}

class DrawableWeapon : WeaponDecorator {

    public DrawableWeapon (Weapon weapon) : base(weapon) {

    }

    public override void Fire() {
        PlayShakingEffect();
        base.Fire();
    }

    private void PlayShakingEffect() {

    }
}

Having this code we can make any type of Weapon drawable. 有了此代码,我们可以使任何类型的Weapon可绘制。 Note all weapons are still instance of Weapon . 请注意,所有武器仍然是Weapon实例。

Weapon machineGun = new MachineGun();
Weapon handGun = new HandGun();

Weapon drawableMachineGun = new DrawableWeapon(new MachineGun());
Weapon drawableHandGun = new DrawableWeapon(new HandGun());

Perhaps a different way of looking at this is to create a composition of different classes rather than use classic OO inheritence. 也许看待这种情况的另一种方式是创建不同类的组合,而不是使用经典的OO继承。 This emphasises the use of interfaces rather than class hierarchies where general purpose code is not inherited but consumed. 这强调了接口的使用,而不是不继承而是使用通用代码的类层次结构。 Example; 例;

interface IDrawer 
{
    void Draw();
}
class WeaponDrawer : IDrawer // class carries out the drawing of a weapon

class Weapon : IDrawer
{
    private IDrawer : weaponDrawer = new WeaponDrawer();
    // Delegate the draw method to a completely different class.
    public void Draw()
    {
        this.weaponDrawer.Draw();
    }
}

This follows the SOLID principles by keeping the definition of Weapon seperate from the function of drawing the weapon. 这通过遵循SOLID原理,将武器的定义与绘制武器的功能分开。 (You could of course use an IOC container instead of the "= new WeaponDrawer()"). (您当然可以使用IOC容器代替“ = new WeaponDrawer()”)。 You end up with a set of single purpose classes instead of a complex inheritence hierarchy - it looks like more code, but you might well find that the design is clearer and more maintainable. 您最终得到了一组单一目的的类,而不是一个复杂的继承层次结构-看起来像更多的代码,但是您很可能会发现设计更清晰,更可维护。

Another approach, using method injection to allow multiple drawer implementations, while you can add IDrawable where needed. 另一种方法是使用方法注入来允许多个抽屉实现,同时可以在需要的地方添加IDrawable。

    interface IDrawable {
       Draw(WeaponDrawer)
    }

    class DrawableWeapon : Weapon, IDrawable {
      Draw(WeaponDrawer wd){
        wd.Draw(this);
     }
    }

    class WeaponDrawer {
       Draw(Weapon weapon){
          //drawing logic here
       }
    }

You can use generics and the decorator pattern to implement the DrawableWeapon 您可以使用泛型和装饰器模式来实现DrawableWeapon

public class DrawableWeapon<T> : Weapon where T : Weapon
{
     T _weapon;

     public void Shot()
     {
        _weapon.Shot();
     }
}

In this way you get a distinct DrawableWeapon class for each weapon you implement. 这样,您为实现的每种武器都会获得一个独特的DrawableWeapon类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM