Inheritance design using Interface + abstract clas

2019-03-15 13:44发布

问题:

I'm not really sure how to title this question but basically I have an interface like this:

public interface IFoo
{
    string ToCMD();
}

a couple of absract classes which implement IFoo like:

public abstract class Foo : IFoo
{
   public abstract string ToCMD();
}

public abstract class Bar : IFoo
{
    public abstract string ToCMD();
}

then classes which inherit Foo and Bar:

public class FooClass1 : Foo
{
    public override string ToCMD()
    {return "Test";}
} ///there are about 10 foo classes.

public class BarClass : Bar
{
    public override string ToCMD()
    {return "BarClass";}
} ///about the same for bar classes.

I am doing this so that when I have my custom list like:

public class Store<T> : List<T>  where T : IFoo {}

I then can restrict the types that go in it but by having the interface it will still take any type of IFoo.

Something like:

Store<Foo> store = new Store<Foo>(); //Only Foo types will work.
store.Add(new FooClass1()); //Will compile.

Store<IFoo> store = new Store<IFoo>(); //All IFoo types will work.
store.Add(new FooClass1()); //Will compile.
store.Add(new BarClass()); //Will compile.

My question is: Is this an ok way of going about this? or is there a better way?

EDIT: Picture->

回答1:

The need for an inheritance chain is questionable, in general.

However the specific scenario of combining an abstract base class with an interface.. I see it this way:

If you have an abstract base class like this, you should also have a corresponding interface. If you have an interface, then use the abstract base class only where the inheritance chain is sensible.

That said, if I'm writing a library and this is part of my API/Framework, I will generally include a "default implementation" that can be used as a base class. It will implement the interface methods in a naive, general way, where possible, and leave the rest for inheritors to implement/override as needed.

This is just a convenience feature of the library though, to assist people who want to implement the interface by providing a functional example that may cover most of what they need to implement already.

In short, the interface is more valuable than the base class, but a base class might save a lot of time and reduce buggy interface implementations.



回答2:

you need the interface; you may or may not need the abstract class.

in general, if you can provide some useful behavior in a base class, then provide a base class; if the base class is not complete by itself then make it abstract (MustInherit in VB parlance)

otherwise, the interface is sufficient



回答3:

Well, that's what the where keyword is for. You probably need to evaluate your object model to make sure that the depth of your inheritance is necessary. Deep inheritance hierarchies tend to complicate projects and are generally a red flag, but it depends on the situation.

Usually, you don't need the abstract class to pull off the functionality you're talking about with the lists, and interfaces are the 'preferred' method for specifying type restrictions. I'd only use the abstract version of your class if there is common functionality you want to encapsulate.

Short answer: make sure you're not going inheritance crazy.

Hope that helps!



回答4:

You could also just use interfaces. There is no reason to use an abstract class.

public interface Foo : IFoo
{
}

 public interface  Bar : IFoo
{
}


回答5:

I am not quite sure if this is what you are looking for but perhaps what you want to do is scrap the interface all together and do this:

abstract class Base
{
    public abstract string ToCMD();
}

abstract class Foo : Base { }

abstract class Bar : Base { }

Hopefully you have other members in the Foo and Bar classes! This will allow you to either restrict your custom collection by Base or just use a plain List<Base>.