-1

I've ran into a problem that is new for me. Basically, someone else has already written a class A. The important parts looks like this

class A{

 // some instance variables

 public A(){
  // Calls methods
  build();
  // Calls more methods
 }

 private build(){
  item = makeItem();
  anotherItem = makeAnotherItem();
  // more code
 }

 private makeItem(){
  // Does some things and calls updateItem()
 }

 private updateItem(){
  // Does some things with instance variables of class A
  // and calls yet another method in class A.
 }

My problem is that build() does exactly what I need, but I need it in another class. Now here are the problems:

  1. class A does a whole lot more than the things I've written, and so I cannot create an object of it. It would be pointless.
  2. I've tried copying the build() method for my class B. However, build() uses other methods. And so I have to copy them as well and of course they call other methods and use instance variables declared in some other methods. Basically, I would have to copy 200 rows of code.

I'm guessing this problem actually has a name but I do not know what it's called and have therefore searched some basic terms only. What can I do to use build() in my class B?

hokosha
  • 305
  • 2
  • 4
  • 11
  • Make it `public`, remove unnecessary methods, create an instance of `A` and use `build()`. Or if the state is not important, make it a `static` class and use `build()` directly. – Maroun Feb 16 '16 at 08:04
  • 1
    First approach : Extract the common code in a separate abstract class AbstractA, make A and B extend AbstractA. Second approach: extract common code in a concrete class C and use C as a delegate in A and B. There could be other solutions, but it's impossible to help you more without concrete code. – Gauthier JACQUES Feb 16 '16 at 08:07
  • "class A does a whole lot more than the things I've written" - be sure that makes sense before going down a rabbit hole. Beyond that you might be looking at a `Builder` pattern. – ChiefTwoPencils Feb 16 '16 at 08:07
  • 1
    reduce the code to the point where only the code is left that you want to "copy". Make this a class, now you could just create another class and make it extend `A`, and you could include the new functions here. – SomeJavaGuy Feb 16 '16 at 08:07
  • Please add more information. Most of the answers given so far would make sense in many cases but could also be misleading. As long as we do not have more information about the relatioship between A and B, we can only speculate. – Frank Puffer Feb 16 '16 at 08:16
  • Thanks for all the answers. @FrankPuffer I do recognize that I was not specific enough. However, I'm pretty sure something here has to work. I'll try some approaches and I'll see. Class A and B are in completely different packages, but I'm guessing that doesn't change much. – hokosha Feb 16 '16 at 08:26

3 Answers3

2

You use the code of the build method in two classes but inheritance is not useful? Then you can reuse the code of the build method with composition. (hint Favor Composition over Inheritance) Create a new class C, which contains the build method. The class C is used by the classes A and B via composition. They delegate to the build method of the class C.

See the refactoring method of Martin Fowler.

https://sourcemaking.com/refactoring/smells/duplicate-code also see https://sourcemaking.com/refactoring/replace-inheritance-with-delegation

Zelldon
  • 5,396
  • 3
  • 34
  • 46
0

Always refactor in small steps. e.g. Put stuff together that belongs together, perhaps there is a neccessity for another class C which contains makeItem, makeAnotherItem and the corresponding instance variables. There is no general answer and it depends on how your code exactly looks like

0

first of all if build() in class A is using other private methods of A, that smells like you will need class A itself.

One option could be to create abstract class containing the common methods (including the build method), and extend this abstract class by class A and B. that way you will not have duplicate code

If for some reason you don't want to touch class A, I suggest you create an interface like :

public interface Builder{
    void build()
}

and then implement this interface by your class B, and also extend class A so that you have implementation of the build method.

public class B extends A implements Builder{
    // build() of class A will be used
    // do other staff
}

In doing so, there is no change to class A at all (this might be desired if it is legacy code or something) + Builder can be used as a type in API you want to expose.

LeTex
  • 1,452
  • 1
  • 14
  • 28