How can subclasses share behavior when one already derives from a different base class?
Asked Answered
Y

3

6

I have two classes that implement ISomeBehavior. Now I want them to share functionality. Normally I would replace ISomeBehavior with an abstract class, like SomeBehaviorBase. The problem is that one of the subclasses already derives from another class, and that other class isn’t software we own. (This is C#, so multiple inheritance isn't an option.) The subclass, that derives from the 3rd party class, has no implementation. It simply derives from the 3rd party class, and implements ISomeBehavior, so the 3rd party class can be treated the same way as the other subclasses that implement ISomeBehavior.

What I've done, for the moment, is implement an extension method on ISomeBehavior. Now the consuming code can call the method. The problem with that approach is that I want to force the calling code to use this extension method. I can't remove SomeMethod() from the interface, because the extension method has to eventually call it.

Any ideas on how to let two classes elegantly share the same behavior, when one of them already derives from another, third party, class? Note: The strategy design pattern sounds like it makes sense here, but that pattern is used when behavior varies among subclasses. The behavior here doesn't vary; it just needs to be shared.

Yonyona answered 18/2, 2011 at 14:39 Comment(2)
What is SomeMethod()? You only mention it in the second paragraph, saying you can't remove it - but without giving any idea about why you'd want to remove it.Atharvaveda
I want to remove SomeMethod() so client code can't use it. The extension method will call it though. And client code will call the extension method. The extension method is basically SomeMethod(), but with two additional parameters. This allows the extension SomeMethod() to do some processing before calling SomeMethod.Yonyona
A
5

Is there any reason you can't use composition instead of delegation to implement the class which currently derives from the 3rd party class? Just delegate all the interface methods to an instance of the third party class. That way, if you want to add functionality you can use a common base class.

This won't work in some cases where the object identity is relevant, but in many cases it's a perfectly reasonable design.

Atharvaveda answered 18/2, 2011 at 14:44 Comment(3)
So that would mean the subclass would implement the interface, and simply call the same methods on the third party class. Is that right? Then that subclass would need to hold a reference to the third party class as well. I can give that a shot.Yonyona
@Bob: Yes, that's it exactly.Atharvaveda
Thanks. I can give that a shot and see how it works out. That simulated multiple inheritance comment, above, is intriguing. I want to check that out as well.Yonyona
E
0
    public interface ISomeBehavior
    {
        int Sample();
    }

    public class A : ISomeBehavior
    {
        int ISomeBehavior.Sample()
        {
            return 1;
        }
    }

   static class SomeExtension
   {
       public static int Sample(this ISomeBehavior obj)
       {
           return 2;
       }
   }

and then use this

  A a = new A();
  var a1 = ((ISomeBehavior)a).Sample();    // a1 = 1
  var a2 = a.Sample();                     // a2 = 2
Enochenol answered 18/2, 2011 at 14:48 Comment(0)
L
0

How about something like this:

class MyClass: ThirdPartyClass
{
}

class MyFunctionality
{
     public MyFunctionality(ThirdPartyClass target)
   ...
}

interface IMyFunctionality
{
    public MyFunctionality MyFunctionality;
}

So the interface would enforce that the derived class has to instantiate the add-on member, and the design of MyFunctionality would just operate against a reference to the base class. This might not work if there are protected members that you need internal access to, though.

Lagrange answered 18/2, 2011 at 15:21 Comment(2)
I don't want the interface to enforce instantiation of the third party class, because it only makes sense for one of the subclasses.Yonyona
You would only implement the interface on the subclass where you used it. I mean, you could just add a member of type "MyFunctionality" in the subclass and not use an interface, but I think having an interface expresses the design intent better.Lagrange

© 2022 - 2024 — McMap. All rights reserved.