1

I often find I need the following:

public interface IMyThing
{
    void Function1();
    void Function2();
    void Function3();
    void Function4();
    void Function5();
}

public abstract class BaseMyThing : IMyThing
{
    // Implement a version of Function1, but Function 2-5 is up to the concrete class to do
    public void Function1()
    {
        // Do stuff.
    }

    public virtual void Function2();
    public virtual void Function3();
    public virtual void Function4();
    public virtual void Function5();
}

public class ConcreteMyThing : BaseMyThing, IMyThing
{
    public new void Function2() { /* something */ }
    public new void Function3() { /* something */ }
    public new void Function4() { /* something */ }
    public new void Function5() { /* something */ }
}

This becomes rather annoying - everytime I add something to the interface, I have to go stub it in the abstract class. It's not the end of the world, but I'm curious if I'm doing something suboptimal here - is there a better way to get partial functionality for shared bits of code here?

Eddie Parker
  • 4,770
  • 3
  • 35
  • 43
  • 2
    Why do you need IMyThing at all? It appears that BaseMyThing defines the same interface. – Heinzi Apr 04 '13 at 05:17
  • 4
    Note also that the unimplemented methods in the abstract class should be marked `abstract`, not `virtual`, and the implementations in derived classes should be marked `override` and not `new`. – Anthony Pegram Apr 04 '13 at 05:20
  • 2
    also why you use new keyword instead of override? – Piotr Perak Apr 04 '13 at 05:30

3 Answers3

2

Consider if not deriving base class from the interface works for your case.

You don't need to derive your base class from the interface. Just make it to provide shared functionality and implement interface in derived classes (matching methods will be automatically picked up from base class by an interface).

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
  • Note that some coding standards will tell you to define an interface for each abstract class you create (for example IDesign). – Thorarin Apr 04 '13 at 05:33
1

I can't see any reason for implementing IMyThing in BaseMyThing:

public interface IMyThing
{
    void Function2();
    void Function3();
    void Function4();
    void Function5();
}

public abstract class BaseMyThing
{
    public void Function1() {}
}

public class ConcreteMyThing : BaseMyThing, IMyThing
{
    public void Function2() { }
    public void Function3() { }
    public void Function4() { }
    public void Function5() { }
}
Dennis
  • 37,026
  • 10
  • 82
  • 150
  • The naming would be rather confusing in this case. `BaseMyThing` does everything `IMyThing` doesn't? Also, when using interface types for variables in your code, you would not have access to `Function1` which may be a problem. – Thorarin Apr 04 '13 at 05:36
  • OP didn't say anything about use cases, so, thinking out is unnecessary. About the naming - it's just a sample. – Dennis Apr 04 '13 at 05:40
  • I wouldn't say it's unnecessary to highlight pros and cons in a complete answer. Does this solve the duplication? Yes. Is it any better than the situation before? No. – Thorarin Apr 04 '13 at 05:46
  • @Thorarin: of course it *is* better. Again, without uses cases, one can't answer more concrete. – Dennis Apr 04 '13 at 05:56
0

I assume Function2 to Function5 is not used in base class but in the derived class. Then it should not be added in IMyThing, instead it should has an individual interfaces each.

Example:

public interface IMyThing
{
    void Function1();
}

public abstract class BaseMyThing : IMyThing
{
    // Implement a version of Function1, but Function 2-5 is up to the concrete class to do
    public void Function1()
    {
        // Do stuff.
    }
}

public interface IMyThingConcrete{
  void FunctionConcrete();
}

public class ConcreteMyThing : BaseMyThing, IMyThingConcrete
{
    public void FunctionConcrete() { /* something */ }
}

Moreover, you don't need to re-implement IMyThing in ConcreteMyThing, it already implemented IMyThing, since it inherited BaseMyThing.

Example to access FunctionConcrete from ConcreteMyThing:

public void AccessFunctionConcrete(IMyThingConcrete myThing){
  myThing.FunctionConcrete();
}
Thorarin
  • 47,289
  • 11
  • 75
  • 111
Fendy
  • 4,565
  • 1
  • 20
  • 25
  • In order to not make the consuming code fugly, I would suggest `interface IMyThingConcrete : IMyThing`, so you still have access to `Function1` without casting. – Thorarin Apr 04 '13 at 05:42
  • I'm having difficulty understanding the requirement of IMyThing and IMyThingConcrete. I do agree to inherit `IMyThing` to `IMyThingConcrete`, but if the domain are different, it will cause code smell. – Fendy Apr 04 '13 at 05:56