Adapter Pattern - Having adapter be same type as adaptee

I am trying to adapt a PEAR Html Select class:

	
class HSelectBoxAdapter
{
   function HSelectBoxAdapter($name='selectbox', $value=NULL)
   {
      new HTML_QuickForm2_Element_Select($name, array('value' => $value));
   }
}


I want this to create an object of type HTML_QuickForm2_Element_Select, but instead it creates it of type HSelectBoxAdapter. Is there any way to have it be created of type HTML_QuickForm2_Element_Select, without using inheritance because I want it to inherit another base class to use its methods, and PHP doesn’t support multiple inheritance.

HTML_QuickForm2_Element_Select is a part of the PEAR QuickForm library, s/he would have to modify an external library source code, and while not strictly breaking OCP, you would have to change a third party library resulting in loss of changes anytime you upgraded.

Cheers,
Alex

I’m not sure what it is your trying to do, but the object instance will be of whatever type your adapter is. You can however, avoid inheritence and use composition/injection.

class HSelectBoxAdapter
{
   private $object = null;

   function __construct($object)
   {
      $this->object = $object;      
   }

}

$object = new HSelectBoxAdapter
(
  new HTML_QuickForm2_Element_Select($name, array('value' => $value))
);

Now you need to automatically delegate every method call on the HSelectBoxAdapter object to the HTML_QuickForm2_Element_Select object (implement __call on the adapter) or manually implement the delegates in the adapter if you need to provide only a limited interface to the encapsulated object.

This way, you at least have the ability to inherit the HSelectBoxAdapter from another object.

Cheers,
Alex

TomB, PcSpectara - Yea, I’m trying to do it so I don’t have to modify the orignal class, as I thought this was one of the main reasons to use the adapter pattern.

PcSpectra - Also, I want the type that I get back to be an object of HTML_QuickForm2_Element_Select type, as I will need to pass this to other
classes that need to use it as that type, not the adapters type.

Consider yourself blessed for that. If inheritance is like playing russian roulette, multiple inheritance is like playing it with a machine gun. You can do it… but only very carefully.

I am “assuming” that the point here is you want to be an pass the class to anything which would accept the original class. i.e. you want to be able to take advantage of software architecture designed to facilitate the original class, but you want to be able to use your modified version instead. This is one of the nasty things about inheritance and why it’s so problematic. The ONLY way you can do that under inheritance is to subclass which you’ve said you don’t want to do. That’s why you’re hearing all these workarounds. Because among other drawbacks, inheritance absolutely requires this, no exceptions.

As PCSPectra mentioned, if the architecture that you’re using is third party and you need to upgrade periodically, then you are out of productions options. However, if it’s something you don’t plan to upgrade or (better) if it’s software architecture classes / functions that you’ve created yourself, you can rewrite the architecture. That’s a pain, but if you only have to do it the one time, then it’s definitely worth the investment to rebuild it correctly.

As TomB demonstrates, the “right way” to build all this is not depending on classes (even abstract classes if at all possible) but on interfaces. Then as PCSpectra demonstrated, you can much more flexibly build classes that implement an interface like TomB, but get their power by calling in the functionality of other classes (composition vs. inheritance). That let’s you choose your functionality in your runtime code, letting you even change the composed class via a factory in the runtime code which opens the possibility that not only do you enjoy late binding, you can actually choose the composed class based on user input making the act of composition fully interactive. Something which makes so much more sense and is entirely impossible with inheritance. So while there are still legitimate uses for inheritance, you can see you can get a lot more functionality and flexibility using other tools in many or most of the cases where developers have previously used inheritance.

As mentioned above there are 2 methods to implement the Adapter pattern: Composition and Inheritance(in languages allowing multiple inheritance or via a trick to [URL=“http://www.factorypattern.com/how-to-simulate-multiple-inheritance-in-java/”]simulate multiple inheritance in other languages). Luckily( or not), Pear supports multiple inheritance. Personally I don’t any of the options more robust when we are talking about code changes in the original Adaptee code. Code changes of course refers to signature changes.

When a change is done in the Adaptee it should be reflected in the Adapter in both the cases(Composition/Inheritance). The drawback seems to come only in the multiple inheritance case.

There is a specific scenario when the methods exposed by the Adaptee are exposed by the Adapter, avoiding that way to write some code in the Adapter(The methods are already inherited from the adapter so there is no need to declare them again). But this is not a real adapter, because the Adaptee could be used directly.

You’re best off defining an interface which they both implement.


interface SelectBox {}

class HTML_QuickForm2_Element_Select implements SelectBox {}

class HSelectBoxAdapter implements SelectBox{}

This way both objects will have a type of “SelectBox”.