user3114009
user3114009

Reputation: 261

Best way to avoid duplicate code if two classes extending different class

I am working on an Android project and i am facing this situation.

I have 2 class :

class A extends B
{

openDoor(){
//impl
}

closeDoor(){
//impl
}

}

class X extends Y{

openDoor(){
//impl
}

closeDoor(){
//impl
}

}

Now if you observe the are two methods common in both the classes openDoor() and closeDoor()

what is the best way to avoid duplicate methods?

My Approach

class ContainingDuplicateMethods{

     openDoor(){
    //impl
    }

    closeDoor(){
    //impl
    }

    }
   }

Create a object of ContainingDuplicateMethods in both the class and call the methods, which we call it as Strategy Pattern,but is this the best solution? why because in large projects we cannot follow this approach and people say it not GOOD PRACTICE, in that case what approach do i need to follow ?

Please note that class A and X are already extending other classes and also i dont want to use static because - Static members are loaded into memory when the program execution starts and will be in memory until the program is terminated, say my code runs continuously for days or weeks and keeps on creating many number of objects using the static references so there might be a chance that we could run out of memory.

Upvotes: 14

Views: 13658

Answers (6)

Nishant Lakhara
Nishant Lakhara

Reputation: 2445

This is the implementation of the answer posted by Tim B. It is a very flexible approach to go with. It is following the principles of object oriented reuse :

  1. Identify that varies and separate them from what stays the same.
  2. Program to an interface , not an implementation.
  3. Favor object composition over inheritance.

    public class Main {

        public static void main(String[] args) {
            X x = new X();
            A a = new A();
            x.getDoor().open();
            x.getDoor().close();
            a.getDoor().open();
            a.getDoor().close();
        }
    }
    
    
    interface HasDoor {
        Door getDoor();
    }
    
    interface Door {
        public void open();
        public void close();
    }
    
    class A extends B implements HasDoor {
    Door d;
    
    @Override
    public Door getDoor() {
        Door door = new Door() {
            public void open() {
                System.out.println("Open A's Door");
            }
    
            public void close() {
                System.out.println("Close A's Door");
            }
        };
        return door;
    }
    

    }

    class X extends Y implements HasDoor{ Door d;

    @Override
    public Door getDoor() {
        Door door = new Door() {
            public void open() {
                System.out.println("Open X's Door");
            }
    
            public void close() {
                System.out.println("Close X's Door");
            }
        };
        return door;
    }
    

    }

    class B {} class Y {}

If you do not want to use HasDoor interface, you can declare constructors inside the class X and class A that initializes the Door instance.

Example ;

class X extends Y {
    Door d;
     public X() {
         d = new Door() {
            public void open() {
                System.out.println("Open X's Door");
            }

            public void close() {
                System.out.println("Close X's Door");
            }
        };

     }



}

Upvotes: 3

Tim B
Tim B

Reputation: 41188

"Favour composition over inheritance" is a useful thing to remember.

Have a Door class with open and close. Include a Door as a member of both A and B.

Voila, job done.

So A.getDoor().close(). B.getDoor().open() etc.

If you need a common interface for both A and B (so you can use either somewhere) then create

interface HasDoor {
    Door getDoor();
}

Now A and B can extend any class you like and implement HasDoor. Any class requiring a door can accept a HasDoor (or just directly accept the Door object) and call open, close, etc.

No duplicated code, full flexibility.

If you need your Door to call methods back in A and B then create the Door class as abstract and implement it in A and B as an anonymous inner class. The abstract methods will be called from Door and then you can do whatever processing is needed in A and B when those methods are called.

For example class A becomes:

 class A implements HasDoor {
      private Door door = new Door() {
          @override void notifyDoorChanged(boolean closed) {
                // The door is telling us its been opened or closed
          }
      }

      @override
      public Door getDoor() {
           return door;
      }
 }

Where door is:

 public abstract class Door {
      boolean closed;
      abstract notifyDoorChanged();

      public void close() {
         closed = true;
         notifyDoorChanged(closed);
      }

      // etc
 }

Note that this is similar to the strategy pattern - but its not quite the same. The Strategy pattern has one master object and then you plug in multiple strategies (i.e. different forms of Door). This has one Door and multiple other objects using the same type of Door, although you could extend it to use the Strategy pattern and have multiple door implementations very easily.

Upvotes: 18

Lijo
Lijo

Reputation: 6778

so here your class a and class a has to follow same functions. that is both classes have same functions.

since the classes already extended another class we can use interface

interface door
{
 openDoor(){
    }

    closeDoor(){
    }


}

both class a and x can implement the door interface. enter image description here

A class can implement any number of interfaces but can extend only one class.

if implementation of class door is same we can do like this

class Door
{
openDoor(){
impl//
    }

    closeDoor(){
impl//
    }


}
class A extends b
{
Door d=new Door();
d.opendoor();
d.closeDorr();


}

Upvotes: 1

Rick Royd Aban
Rick Royd Aban

Reputation: 904

public interface YourInterface{
  public void openDoor();
  public void closeDoor();
}

public abstract class YourAbstractClass implements YourInterface{
  public abstract void openDoor();
  public abstract void closeDoor();
}

public class YourClass extends YourAbstractClass{
  @Override
  public void openDoor();
  public void closeDoor();
}

public class YourSubClass extends YourClass{
  //you can just call super methods here
  super.openDoor();
  super.closeDoor();
}

Upvotes: 0

dronidze
dronidze

Reputation: 96

I think you should create an interface with methods openDoor() and closeDoor(). After that inherit classes A and X from this interface and implement methods. If methods implementation are similar then you can create utility class with static methods.

Upvotes: 0

Scary Wombat
Scary Wombat

Reputation: 44834

Yes, create an abstract class which contains the common code. Have this abstract class implement an interface which contains the necessary methods.

Have both other classes extend the abstract class.

Upvotes: 0

Related Questions