RobbinMarcus
RobbinMarcus

Reputation: 336

C# Inheriting polymorphic types

Starting out with a basic class called Weapon, I intended it to be polymorphic as follows:

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.

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.

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.

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?

Upvotes: 1

Views: 528

Answers (5)

Kao
Kao

Reputation: 7364

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
    }

Upvotes: 4

Davide Lettieri
Davide Lettieri

Reputation: 326

You can use generics and the decorator pattern to implement the 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.

Upvotes: 0

Robert
Robert

Reputation: 3302

Another approach, using method injection to allow multiple drawer implementations, while you can add IDrawable where needed.

    interface IDrawable {
       Draw(WeaponDrawer)
    }

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

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

Upvotes: 0

PhillipH
PhillipH

Reputation: 6222

Perhaps a different way of looking at this is to create a composition of different classes rather than use classic OO inheritence. 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. (You could of course use an IOC container instead of the "= 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.

Upvotes: 0

Mehmet Ataş
Mehmet Ataş

Reputation: 11549

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. Note all weapons are still instance of Weapon.

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

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

Upvotes: 0

Related Questions