views:

266

answers:

5

So, I'd like to hear what you all think about this.

I have a project where three different inheritance paths need to all implement another base class. This would be multiple inheritance and isn't allowed in C#. I am curious how I can implement this without code duplication.

EDIT: I don't own the three classes. The three classes are from 3rd party code. So I cannot make them all extend my base class.

Right now I am using three different classes, each one extending a different base class. Then I have the same code in each of the three abstract classes.

I could use a single interface, but I would still need to duplicate the code.

I could make some kind of static class that implements the code and then reference that in each of the 3 abstract classes. It would eliminate the duplication, but, I am not sure how I feel about this. I could implement Extensions methods on the interface, but then the interface itself would be empty and the extension methods (containing the duplicate code) would be in a totally different file, which seems not quite right. Plus I can't implement properties in extension methods...

How can I factor out the code duplication here?

EDIT, inheritance tree:

class Class1 : 3rdPartyBaseClass1 { }
class Class2 : 3rdPartyBaseClass2 { }
class Class3 : 3rdPartyBaseClass3 { }

I have code I want to be in each of the above Classes, but I cannot add it to the 3rdPartyClasses.

+1  A: 

Sounds like you need to insert the new abstract class into the inheritance tree at whatever point those three paths come together, but there really isn't enough information to tell. If you could post some of your inheritance tree, that would help a lot.

JoshJordan
I don't own the three classes. Sorry I will add that to my post. the three classes are from 3rd party code.
Alex Baranosky
Actually the code IS open source, so I can theoretically change it. But I'd rather not, and am interested in other ideas for how to tackle it.
Alex Baranosky
+6  A: 

Create an interface that Class1, Class2, and Class3 can implement. Then put your code in extension methods so it will apply to all.

interface IMyInterface {
    void Foo();   //these are the methods that these 
        //classes actually have in common
    void Bar();    
}

public class Class1 : 3rdPartyBaseClass1, IMyInterface {
    // whatever

}

public static class IMyInterfaceExtensions {
    public static void CommonMethod(this IMyInterface obj) {
        obj.Foo();
        obj.Bar();
    }
}

public static class Program {
    public static void Main() {
        var instance = new Class1();
        instance.CommonMethod();
    }
}
recursive
So then leave the interface empty? I can't use this for properties either... Is this as good as it gets with C#?
Alex Baranosky
It just feels a little hackish to create an interface that defines no... interface :) This idea is what I started thinking I would do earlier, but crossed my fingers and hoped someone in cyberspace would have a more elegant "Secret" technique :)
Alex Baranosky
No, the interface would contain whatever the 3 classes actually have in common.
recursive
which is basically nothing in common :) Thanks for the confirmation. I've got some coding to do......!
Alex Baranosky
Ahhh shoot. I realized a small difficulty. What if those methods need to access a private variable? The extension methods won't have any access to the internals of the classes.
Alex Baranosky
Not just extension methods. Your Class1 native methods won't be able to see those either. I'm starting to get confused about what you're actually trying to accomplish.
recursive
If they have nothing in common, then how could there be code duplication in the first place? Where is the duplication?
recursive
I have 3 DIFFERENTLY NAMED CLASSES all extending three unique, 3rd party base classes. But those three differently named classes contain the same exact code.
Alex Baranosky
(but each of those three differently name classes also has a bunch of other code that is different as well)
Alex Baranosky
So in a multiple inheritance language I would put that "same code" into a class, and have my three classes all derive from it (as well as the oriignal 3rd party classes they each derive from currently)
Alex Baranosky
Ok, so, you can put all your common code in a totally different class and let each of your wrapper classes contain an instance of it. You could even expose the instance as a readonly field.
recursive
+5  A: 

OK, you can do something similar to my previous suggestion, and also similar to recursive's suggestion. For the functionality you require in all three of your derived classes, you can create a single Interface along with a single class (call it "Implementer" for kicks) that implements that Interface (and that has the actual code you want executed with each call).

In each of your derived classes, then, you implement the Interface and create a private instance of Implementer. In each of the interface methods, you just pass the call along to the private instance of Implementer. Because Implementer and your derived classes all implement your Interface, any changes you make to the Interface will require you to modify Implementer and the derived classes accordingly.

And all your code is in one place, except for all the lines passings the calls on to the private instance of Implementer (obviously multiple inheritance would be better than this, but you go to war with the army you have, not the army you wish you had).

Update: what about just adding a public instance of your class to each of the derived classes?

public class DerivedClass1 : ThirdPartyClass1
{
    public MyClass myClass = new MyClass();
}

Or if you care who Demeter is and you get paid by LOC:

public class DerivedClass1 : ThirdPartyClass1
{
    private MyClass _myClass = new MyClass();
    public MyClass myClass
    {
        get
        {
            return _myClass;
        }
    }
}

Then you'd just call the MyClass methods like this:

DerivedClass1 dc1 = new DerivedClass1();
dc1.myClass.DoSomething();

This way, we could all go to sleep.

MusiGenesis
Thanks. I had considered this option too. That's why I thought this would be a fun question to learn from. There are so many "one-legged soldiers" to choose from.
Alex Baranosky
@GordonG: actually, answering this question makes me want to switch to a multiple-inheritance language.
MusiGenesis
I've been reading about different options to multiple inheritence, like Scala's traits. I guess that's why I was thinking about this question in the first place.
Alex Baranosky
@MusiGenesis: Adding a public instance field would seem to break encapsulation IMHO. Also the dc1.myClass.DoSomething() violates the "Law" of Demeter, which is another way of saying the same thing.
TrueWill
@TrueWill: happy now? That made a *world* of difference for this code sample. This approach may violate the Law of Demeter, but it obeys the Law of KISS, and violating KISS carries much harsher penalties, IMHO.
MusiGenesis
@MusiGenesis: Hey, I already gave you +1! ;) Yes, that is an improvement. And it's more like the General Guideline of Demeter. The question is if the signature of DoSomething() might change - if so, a change to MyClass could require changes to all of the **callers** of DerivedClass1.
TrueWill
P.S. http://en.wikipedia.org/wiki/Law_of_Demeter
TrueWill
@TrueWill: this is my favorite quote from your wikilink: "A disadvantage of the Law of Demeter is that it sometimes requires writing a large number of small "wrapper" methods ... to propagate method calls to the components. Furthermore, a class's interface can become bulky as it hosts methods for contained classes resulting in a class without a cohesive interface."
MusiGenesis
@MusiGenesis: And that's true. Almost any law, rule, principle, design pattern, etc. for software development has advantages and disadvantages. It's all about knowing the tradeoffs and weighing them for your particular situation, as you said about KISS earlier. But if KISS always won, we'd still be writing procedural code in our Main methods. :)
TrueWill
+4  A: 

Similar to MusiGenesis's suggestion, if you need the functionality of the 3rd party classes but do not have to descend from them, you could use composition as follows:

class ThirdPartyBaseClass1
{
    public void DoOne() {}
}

class ThirdPartyBaseClass2
{
    public void DoTwo() { }
}

class ThirdPartyBaseClass3
{
    public void DoThree() { }
}

abstract class Base
{
    public void DoAll() { }
}

class Class1 : Base
{
    public void DoOne() { _doer.DoOne(); }
    private readonly ThirdPartyBaseClass1 _doer = new ThirdPartyBaseClass1();
}

class Class2 : Base
{
    public void DoTwo() { _doer.DoTwo(); }
    private readonly ThirdPartyBaseClass2 _doer = new ThirdPartyBaseClass2();
}

class Class3 : Base
{
    public void DoThree() { _doer.DoThree(); }
    private readonly ThirdPartyBaseClass3 _doer = new ThirdPartyBaseClass3();
}

This also gives you the freedom to define whatever interfaces you want and implement them on your classes.

TrueWill
The only problem is I end up with even MORE duplicate code this way. I have the same exact properties defined in a bunch of classes, all calling the private member doer's functions. ... Fun discussion, though.
Alex Baranosky
@GordonG - You're correct that you have the same **properties** defined, but there's no duplication of logic - it's all delegation.
TrueWill
@TrueWill: but there *is* duplication of a big mess of useless code.
MusiGenesis
@MusiGenesis: Yes, in a sense. But that duplication is caused by the constraint that we can't modify the original classes. Composition and delegation give us a lot of freedom when we want to reuse logic but add behavior. See http://en.wikipedia.org/wiki/Adapter_pattern
TrueWill
I think that whenever you have a lot unavoidable plumbing code like that, then that's a good opportunity to use code generation. I believe that all those delegating methods could be generated with a T4 template. The T4 template could get the information needed for mapping the methods in a number of ways. Possibly from a config file. Possibly using reflection. Attributes maybe. I think the problem is too underspecified to give a precise answer though.
dangph
+1 *quid pro quo.*
MusiGenesis
@dangph: I'm not a proponent of code generation. I prefer to deal with large masses of useless, repetitious boilerplate code by not having it there in the first place.
MusiGenesis
@MusiGenesis, you are running into a limitation of static typing. Static typing has its advantages and disadvantages, and this sort of issue shows one of its disadvantages. If you were use a duck typed language, I think you wouldn't have this issue. When you have *unavoidable* boilerplate code, then code generation works well. It especially works well in C# because a code generator is built in to the IDE (T4 templates) and you can relegate generated code to partial classes where it won't clash with human-generated code.
dangph
+1  A: 

I think you may want to use composition instead of inheritance. Exactly how to do this depends on what the third party classes look like, and what your own code looks like. Some more specific code relating to your problem would be helpful, but for example, suppose you want to have three different third party GUI widgets that all need to be customized with your own initializer code.

Case 1: Suppose your third party widgets look like:

public interface IThirdPartyWidget {
  public void doWidgetStuff();
}

public class ThirdPartyWidget1: ThirdyPartyWidget implements IThirdPartyWidget {
 ...
}

public class ThirdPartyWidget2: ThirdPartyWidget implements IThirdPartyWidget {
 ...
}

You can do:

public class MyWidget implements IThirdPartyWidget {
 private IThirdPartyWidget delegateWidget;
 public MyWidget(IThirdPartyWidget delegateWidget) {
  this.delegateWidget = delegateWidget;
 }

 public void doWidgetStuff() {
  delegateWidget.doWidgetStuff();
 }
}

Case 2: Suppose you absolutely need to extend those widgets, and you have to refactor your own code:

public class MyWidget1: ThirdPartyWidget1 {
 public void myMethod() {
  runMyCode();
 }

 private void runMyCode() {
  //something complicated happens
 }
}

public class MyWidget2: ThirdPartyWidget2 {
 public void myMethod() {
  runMyCode();
 }

 private void runMyCode() {
  //something complicated happens
 }
}

This can become:

public class MyCodeRunner {
 public void runMyCode() {
  //...
 }
}

public class MyWidget1: ThirdPartyWidget1 {
 private MyCodeRunner myCode = new MyCodeRunner();
 public void myMethod() {
  myCode .runMyCode();
 }
}

public class MyWidget2: ThirdPartyWidget2 {
 private MyCodeRunner myCode = new MyCodeRunner();
 public void myMethod() {
  myCode .runMyCode();
 }
}

Hope this makes sense!

RMorrisey
I should mention that in Case 1, the same approach can be applied to a common parent class, instead of an interface; that is, you might just use a ThirdPartyWidget (base class) reference instead of an IThirdPartyWidget reference.
RMorrisey