0

I have two classes which contains almost same method. How can I refactor this with inheriting one class by other class.

class A{
  public void run(){
    // task 1
    // task 2
    // task 3     
  }
}

class B{
  public void run(){
    // task 1   <- same as in class A
    // task 2   <- same as in class A
    // task 4   <- different from class A
  }
}

I want to refactor this inheritance and overriding. How can I do that. If this code details is not enough this contains the real code. https://dotnetfiddle.net/wvDQDb

4 Answers4

5

You want the Template Method Pattern.

Basically you have run() calling another method (called say stopService()) which implement task3-behavior. Instead of overriding run() in the subclass B you just override the stopService() method to implement task4-behavior instead.

JacquesB
  • 57,310
  • 21
  • 127
  • 176
4

There is a lot of misunderstanding about 'DRY' and 'reusability'. When a developer sees some code that seems to do the same thing, or is a duplicate, the first thought is often: "that has to be refactored". But that is not always a good idea.

This code is a good example of that: there are some methods in two different classes which are the same, and the first thought is: "that has to be refactored into one class using inheritance".

I think that using inheritance is a bad idea in this case. I think that you are better off implementing the tasks in a different class, for example a 'program' class, and call the methods in that class from class A and B.

However, this introduces a dependency between class A and B and the new class with the methods. There are Design Patterns to solve that. But in this case, I think that using inheritance is not the way to go.

Robert Harvey
  • 198,589
  • 55
  • 464
  • 673
Frits
  • 390
  • 2
  • 8
2

To elaborate on Frits's answer: only consider inheritance if it makes sense to say "A is a B" or "B is an A" or "A and B are both C's".

If none of this is the case but you still see repetition that can be generalized, create a new class named ServiceUtils or something like that and move your shared code in there.

Martin Maat
  • 18,218
  • 3
  • 30
  • 57
1

In this specific case, it sounds like you just need a post-processing hook.

In its simplest form, it could look like this:

class BaseClass
{
    protected virtual void PostProcess()
    {
        //No code, do nothing
    } 

    public void Run()
    {
        //Do Task 1
        //Do Task 2
        PostProcess();
    }
}

class A : BaseClass
{
    protected override void PostProcess()
    {
        //Do task 3
    }
}

class B : BaseClass
{
    protected override void PostProcess()
    {
        //Do task 4
    }
}

Another common pattern looks like this:

class BaseClass
{
    public virtual void Run()
    {
        //Do Task 1
        //Do Task 2
    }
}

class A : BaseClass
{
    public override void Run()
    {
        base.Run();
        //Do task 3
    }
}

class B : BaseClass
{
    public override void Run()
    {
        base.Run();
        //Do task 4
    }
}

These show the basics of two common approaches. Depending on your requirements, you might want to make the base class abstract, or you might want to use an event instead of a method for the post-processing hook, or you might wish to extract Task1 and Task2 to separate methods, etc.

You could also solve this problem without inheritance, e.g. you could have a single class and define the post-processing behavior by injecting it, or via composition instead of inheritance.

John Wu
  • 26,032
  • 10
  • 63
  • 84