rohit
rohit

Reputation: 501

How to refactor the following code without killing OOPS in C#

I have 3 interfaces with 2 methods each doing the same job.

Interface A
{
   Void M1()
   Void M2()
}

Interface B
{
   Void M1()
   Void M2()
}

Interface C
{
   Void M1()
   Void M2()
}

Now, There are 3 classes implementing each of these interfaces.

Public Class A1:A
{
  Public void M1()
  {

  }
  Public void M2()
  {

  }
}

Public Class B1:B
{
  Public void M1()
  {

  }
  Public void M2()
  {

  }
}

Public Class C1:C
{
  Public void M1()
  {

  }
  Public void M2()
  {

  }
}

Functionality of M1 and M2 is exactly same in 3 classes. Interfaces are a part of library, I cannot change the interface and also cannot declare a new interface.

I want to refactor this code so that this duplication can be removed. I thought of creating a common class containing this functionality and then calling common class from each of these classes.

Please suggest.

Upvotes: 2

Views: 205

Answers (5)

Jose Lamas Ríos
Jose Lamas Ríos

Reputation: 466

If you only want to avoid to duplicate the implementation of those methods, then your initial approach is correct.

public class HelperClass
{
   public static void M1()
   {
      // implementation code
   }
   public static void M2()
   {
      // implementation code
   }
}

public class A1:A
{
   public void M1()
   {
       HelperClass.M1();
   }
   public void M2()
   {
       HelperClass.M2();
   }
}

public class B1:B
{
   public void M1()
   {
       HelperClass.M1();
   }
   public void M2()
   {
       HelperClass.M2();
   }
}

public class C1:C
{
   public void M1()
   {
       HelperClass.M1();
   }
   public void M2()
   {
       HelperClass.M2();
   }
}

Even if interfaces A, B, and C have the same methods, they may have different semantics and may make sense to have them as separate interfaces. That is, making a class implement A, may mean something different than implementing B, even if their methods have the same signatures.

Adding additional interfaces or common base classes is overkill and adds unneeded coupling. As I said before, if you only need to avoid duplicating the methods' implementation, a helper class is the easiest and cleanest solution.

Upvotes: 0

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236268

public class BaseClass : A, B, C
{
   public void M1()
   {    
   }

   public void M2()
   {    
   }
}

Then just inherit from BaseClass:

public class A1 : BaseClass
{
}

public class B1 : BaseClass
{
}

public class C1 : BaseClass
{
}

A1 still will implement interface A. B1 will implement interface B. Same with C1. So, all your existing code will remain working:

A a = new A1();
a.M1();

Upvotes: 0

Andras Zoltan
Andras Zoltan

Reputation: 42363

Given the odd restrictions (and if you can I really suggest trying to get the interfaces changed) I think this is the best you can do:

public class Base : A, B, C {
  public void M1(){}
  public void M2(){}
}

Now inherit from Base in A1, B1 and C1.

However, if an A cannot, or should not, also be a B then this pattern won't work.

Therefore you would indeed have to go for the next best thing - a common base with the common functionality:

public class Base {
  protected void M1Impl() { /* put your common implementation in here */ }
  protected void M2Impl() { /* put your common implementation in here */ }
}

As the comments say - put the duplicated M1 and M2 code in the M1Impl and M2Impl methods here.

Now you can reuse this base for A, B and C implementations:

//common base for any implementation of A
//repeat for B and C
public class A1Base : Base, A
{ 
  public void M1() { M1Impl(); }
  public void M2() { M2Impl(); }      
}

public class A1 : A1Base { }

I've worked on the basis here that you might have many implementations of A or B or whatever, and therefore you want a common starting point for each of those. If that's not the case, then you can do away with A1Base and simply call it A1.

Upvotes: 0

daryal
daryal

Reputation: 14929

public abstract class XX : X
{
    public void M1()

    {

    }

    public void M2()
    {

    }
}

public interface X : A, B, C
{
}

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1502166

It sounds like you should declare your own interface, and then create an adapter - or possibly multiple adapters. For example:

public interface IUnified
{
    void M1();
    void M2();
}

public class UnifiedAdapter : IUnified
{
    private Action m1;
    private Action m2;

    public UnifiedAdapter(A a)
    {
        m1 = () => a.M1();
        m2 = () => a.M2();
    }

    public UnifiedAdapter(B b)
    {
        m1 = () => b.M1();
        m2 = () => b.M2();
    }

    public UnifiedAdapter(C c)
    {
        m1 = () => c.M1();
        m2 = () => c.M2();
    }

    public M1()
    {
        m1();
    }

    public M2()
    {
        m2();
    }
}

(This uses delegates to avoid having to create multiple adapter classes. The best approach depends on your exact situation.)

Upvotes: 2

Related Questions