6

I have a problem with using the right inheritance-chain without loosing good parts of the DRY-principle.

Given the following structure:

  • abstract class A is my base for all classes
  • abstract class B : A is my base for all classes that can have special features (made available through B)

Now, I need to have two new classes which share the same features. But one is of type A whilst the other one is of type B. (This can not be changed!) Both classes should have a method SetSize().

So at the end there would be class C:A and D:B, both to have the same SetSize method.

Question: How would I create a base-class, intermediate layer to have the SetSize()-method only declared/implemented once (DRY)? I guess something about using interfaces or some static helper-classes to implement the logic of SetSize()?

Are there any patterns or best-practices to achieve this behavior?

KingKerosin
  • 3,639
  • 4
  • 38
  • 77
  • 2
    Related - [Prefer composition over inheritance](http://stackoverflow.com/questions/49002/prefer-composition-over-inheritance) – Eugene Podskal Jul 10 '16 at 10:37
  • Is the behavior of `SetSize` will be same for all implementations? (both for classes of type A and B, as you have mentioned `dry`)? – Yogi Jul 10 '16 at 12:04
  • @Yogi The method will be exactly the same for both implementations. Thats why I'm looking for a way to have it at one single point – KingKerosin Jul 10 '16 at 12:08

2 Answers2

2

You can't do this via inheritance in C# because it doesn't support multiple inheritance; the tool the language gives you for this scenario is interfaces:

public interface  
{     
    void SetSize(Size size);
}

public SizableA: A, ISizable { ... }
public SizableB: B, ISizable { ... }

Also bear in mind that inheritance should be used when the types in the inheritance chain have a is a relationship (a Cat is an Animal, a B is an A, etc.) while interfaces are preferred when completely unrelated classes have a very specific common behavior; IEquatable, IComparable, IDisposable, etc. Your SetSize behavior seems to fit better in this last category as it doesn't seem to be a functionality specific to A or B.

Now, if both SizableA and SizableB should share the same implementation of SetSize then the best solution is to use composition or simply delegate functionality:

public interface ISizable
{
     void SetSize(Size size, ISetSizeProvider provider); //Alternatively inject provider in SizableA and SizableB's constructor to get composition.
}
InBetween
  • 32,319
  • 3
  • 50
  • 90
0

Make an abstract class include SetSize() method and common properties of A and B classes.Then A and B classes inherit the abstract class.

Mehmet
  • 739
  • 1
  • 6
  • 17