简体   繁体   中英

Base class in C#… that can be inherited from like an interface?

I need to implement a basic behaviour for many classes. To make an example, let's say it is a sort of drawing behaviour: there are many different type of objects that may be drawn, and they all need a few attributes and some common code to implement the drawing process. Let's say I put this common part in a class called Drawable.

The problem is that these different classes may well be extending other classes, so I can't have them inherit from Drawable. The obvious solution would be using an interface (IDrawable), but then I couldn't implement any code in it; another solution I can think of would use composition, by creating a DrawAction class that all of my classes would instantiate, but this would require me to put the same code (if just a couple of lines) in all the classes that I need to make drawable.

Can someone please give me suggestions on how to do this? Thanks.

You can create instance of DrawAction class and then just inject it into other classes using constructor dependency injection rather than explicitly instantiating it by each class, this give you less coupled design as well:

IDrawAction drawAction = new DrawAction();
var drawable = new Drawable(drawAction);

public class Drawable
{
    public Drawable(IDrawAction drawAction)
    {
    }
}

This may be a situation for composition , rather than inheritance.

You could implement the drawing behavior in one class, and then have all the classes that need it maintain a reference to it.

If you need to support many different drawing algorithms, you might want to look at the Strategy Pattern . Here you would implement many different drawing algorithms, all implementing some sort of interface, and the object that needs to draw would have a reference to one of them.

Depending on your situation, if certain types of objects always need a certain type of drawing algorithm, the selection of which drawing class could be automated with the use of an IoC container, like StructureMap or Unity .

Here's an example of the strategy pattern from DoFactory

You can create extension methods for IDrawable :

public static class DrawableExtensions
{
    public static int CalculateSize(this IDrawable drawable)
    {
         return drawable.Width * drawable.Height;
    }
}

This way these methoda apear to be on the IDrawable interface:

IDrawable d = new Circle();

int size = d.CalculateSize();

The downside is that extension methods are static and you can't override them.

C# doesn't supports multiple inheritance. Stop. You cannot do that. You are talking about "Mixins"... that are still not supported in C#.

However there are several alternatives you can use.

The simpler one is to use a Mixin class that you can add as a field in all your classes. For example...

public class DrawerMixin
{
    public void DrawRectangle() { ... }
}

public class MyClass1 : Component
{
    public DrawerMixin Drawer { get; private set; }

    public MyClass1()
    {
        this.Drawer = new DrawerMixin(this);
    }

    public MyClass1(DrawerMixin drawer)
    {
        this.Drawer = drawer;
    }

    public void MyFunc()
    {
        ...
        this.Drawer.DrawRectangle();
    }
}

It sounds like the Decorator pattern may be appropriate for what you are trying to achieve.

See Decorator Pattern Wikipedia entry

  • Instead of trying to inherit the common "Drawing" logic, place the common logic in another class ie, a "Draw* er *"
  • When an object must be drawn, pass it to the appropriate Draw* er * (or make a Draw* er * for it)
  • You may still find an IDrawable interface useful so that the Draw* er * code can be written against a known interface.
  • You may end up with multiple Draw* er * implementations (in which case you will need to handle dynamic selection of the appropriate Drawer for each object to be drawn)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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