-1

I am facing a problem with changing behaviour of a library (thus cannot or don't want to change its internals because of future updates, etc.).

In this library there is an abstract class which shares few methods with all its subclasses. Now I need to change few methods in this abstract super class without changing the subclasses. I was wondering what pattern I should apply to this without rewriting the whole thing.

I use PHP, so I could use a trait to override these methods in my own sub-subclasses which I will then use in my client code. This would result in creating the sub-subclasses and adding a trait (which is a one-liner). But I need to run PHP 5.3 which doesn't support traits.

Is there a pattern that solves this problem?

EDIT 2: the point is I don't want to change the library code, I can extend the subclasses and use them in client code but I don't want to change the code in the library itself (so I can update the library easily).

EDIT: see simplified code below

abstract class SuperClass {
    protected function doMagic() { 
        ... I need to change this ...
    }

    abstract public function execute();
}

class SubClass1 extends SuperClass {
    protected public execute() {
        $this->doMagic();
        ... some other code ...
    }
}

class SubClass2 extends SuperClass {
    protected public execute() {
        $this->doMagic();
        ... some different code ...
    }
}
6
  • The pattern is called functional programming (as opposed to OOP).
    – Job
    Feb 19, 2013 at 21:38
  • 1
    couldn't you make another object, and forward all calls to the existing library. This way the abstract class does not need to be changed at all, but you get all the advantages of changed interface.
    – tp1
    Feb 19, 2013 at 21:38
  • Would you mind sharing a code sample that illustrate your specific situation? Feb 19, 2013 at 21:47
  • @tp1 I couldn't because the methods I need to change are used from within these subclasses. I edited the post
    – redhead
    Feb 19, 2013 at 21:58
  • What you want to do is against the open / closed principle. Are you sure you want to change the behaviour of an already implemented class and propagate this change to all its subclasses?
    – Giorgio
    Feb 20, 2013 at 9:21

3 Answers 3

1

First question--why do you need to change the logic of the abstract class? You seem to indicate that you don't want any of its current subclasses to inherit the changes, so I have to assume you want to write new subclasses which will. Given that the new subclasses don't exist yet, add a little indirection first:

abstract class SuperClass {
    protected function doMagic() { 
        ... I need to change this ...
    }

    abstract public function execute();
}

abstract class ExtendedSuperClass extends SuperClass {
    protected function doMagic() { 
        ... NEW CODE ...
    }
}


class SubClass1 extends SuperClass {
    protected public execute() {
        $this->doMagic();
        ... some other code ...
    }
}

class SubClass2 extends SuperClass {
    protected public execute() {
        $this->doMagic();
        ... some different code ...
    }
}

class SubClass3 extends ExtendedSuperClass {
    protected public execute() {
        $this->doMagic();
        ... yet more different code ...
    }
}

That is, extend the abstract class with a new abstract class, and have the classes needing the new logic extend THAT.

5
  • Sorry, maybe I wrote that wrong. There are no new classes, the subclasses already exist in the library and are using its abstract parent methods (that I need to change). So, basically I want the existing subclasses having the common behaviour (which is in the super class and which I need to change). To be concrete: in your code, there are 2 classes (1 and 2) which don't have the same changed behaviour as the new class (3), but this is exactly what I need.
    – redhead
    Feb 19, 2013 at 23:11
  • 1
    @redhead So, if you change the behavior in the abstract class that the current subclasses are inheriting, do you want them to inherit the new behavior? If so, just change the logic in the abstract class and they'll inherit it. If you don't want them to inherit it, what's the point of changing the abstract class? Feb 19, 2013 at 23:22
  • That's the thing, I don't want to touch these classes in the library (for sake of updating, etc.). I can use the subclasses in my client code (I can also extend them) but I don't want to touch the code in them. That's why I ask. If I just edit the code in the library what is the point of asking this question looking for a way not to edit it.
    – redhead
    Feb 19, 2013 at 23:29
  • @redhead Then if you can't edit any code, you can't change the behaviour. If the internals of a class are not doing what you want, you must crack it open and implement what you need. There is really no other way. Feb 20, 2013 at 13:42
  • @redhead - Try copying the class that needs modifying into a new class (keeping the same names). Modify the copy. Put the modified copy ahead of the library in your class path (or use an AutoLoader or whatever you to in PHP?). Feb 20, 2013 at 21:31
0

Abstract classes should be written without considering their subclasses in order to avoid tight coupling. I don't know what your specific situation is, but usually abstract classes are meant to be used for polymorphism, with each subclass implementing a specific behavior through an abstract method. If you find yourself changing code inside the base class which will break the subclasses, you have a coupling problem. Base classes should make calls to abtract methods which the subclasses will implement. Moreover, a subclass should limit the number of calls to parent methods.

5
  • I see what you mean. The thing is, the library is designed this way, so I have no power over it. The coupling problem is there - subclasses call its parent methods (which I need to change).
    – redhead
    Feb 19, 2013 at 22:06
  • @redhead well if you can change the abstract class, why not change the subclasses also ? Feb 20, 2013 at 0:06
  • I don't want to change the abstract class (meaning the code of it), it's a library and I want to be able to update it later. I don't want to change any code in the library itself. I can extend the subclasses and then use them in client code. But I don't want to change the code of the library classes themselves. That's why I am asking. If I could edit the code in the abstract class I wouldn't be asking.
    – redhead
    Feb 20, 2013 at 0:59
  • Then what you can do is create another class yourself, which inherits the abstract class and provides the new behaviour by overriding the doMagic method, and then you can make your subclasses inherit from your new class, exactly like Matthew Flynn suggested. It seems like there is no other way. Feb 20, 2013 at 13:38
  • But that way the existing subclasses in the library would have to be rewriten to use my own abstract class which is what I wanted to avoid. I think there is no other way after all.. :/
    – redhead
    Feb 20, 2013 at 14:03
0

I see no design pattern, but, an algorithm.

Original Code:

 abstract class SuperClass {
     protected function doMagic() { 
         ... I need to change this ...
     }

     abstract public function execute();
 } // class

 class SubClass1 extends SuperClass {
     protected public execute() {
         $this->doMagic();
         ... some other code ...
     }
 } // class

 class SubClass2 extends SuperClass {
     protected public execute() {
         $this->doMagic();
         ... some different code ...
     }
 } // class

New Code:

 abstract class SuperClass {
     protected $UseNewSpell = false;

     protected function OldSpell() {
        // put previous code here
     }

     protected function NewSpell() {
        // put new code here
     }

     protected function doMagic() { 
         if ($this->UseNewSpell) {
            $this->NewSpell();
         }
         else {
            $this->OldSpell();
         }                 
     }

     abstract public function execute();
 } // class

 class SubClass1 extends SuperClass {
     protected public execute() {
         $this->UseNewSpell = false;

         $this->doMagic();
         ... some other code ...
     }
 } // class

 class SubClass2 extends SuperClass {
     protected public execute() {
         $this->UseNewSpell = false;

         $this->doMagic();
         ... some different code ...
     }
 } // class
1
  • But this means rewriting the library code. That isn't the way to go as I stated in the question.
    – redhead
    Feb 19, 2013 at 22:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.