-1

Once in a while I’m stumbling on switch statements during a Code Review session.

I would like to find a more elegant way of this code

....

$istannceOfClass = $repository->loadFoo(); 
switch($istannceOfClass) 
{  
    case $istannceOfClass instanceOf derivedClassAB:
        $istannceOfClass->callA(); 
        $istannceOfClass->callB(); 
        break;
    case $istannceOfClass instanceOf derivedClassCD:
        $istannceOfClass->callC(); 
        $istannceOfClass->callD(); 
        break;
    case $istannceOfClass instanceOf derivedClassEF:
        $istannceOfClass->callE(); 
        $istannceOfClass->callF(); 
        break;
}

I thought about improve the code. could the anonymous class be used? I can not change the hierarchy and subclasses of $istannceOfClass and $istannceOfClass itself.

an attempt: to improve, correct, throw I used anonymouse for convenience. Code that can not be changed

interface baseclass { }

class ab implements baseclass 
{
    public function callA()
    {
        return "<br>class ab Call A";

    } 

    public function callB()
    {
        return "<br>class ab Call B";
    } 
}

class cd implements baseclass 
{
    public function callC()
    {
        return "<br>class cd Call B";

    } 

    public function callD()
    {
        return "<br>class cd Call C";
    } 
}

New code for refactor first common interface with all methods

interface commonABCDEF 
{
    public function callA(); 
    public function callB();
    public function callC(); 
    public function callD();
    public function callE(); 
}

second abstract class for default behaviour

class abstractCommonAbcdef implements commonABCDEF
{    
    //common behavior
    public function callA() { return '<br>default A'; }
    public function callB() { return '<br>default B'; }
    public function callC() { return '<br>default C'; }
    public function callD() { return '<br>default D'; }
    public function callE() { return '<br>default E'; }
    //abstract public function run(); 

}

adapter for case 1 of switch

$abOverride = new class(new ab()) extends abstractCommonAbcdef 
{   
    public function __construct(baseclass $abcde)
    {
        $this->abcde = $abcde;
    }     

    public function callA() 
    {
        return $this->abcde->callA(); 
    }

    public function callB() 
    {
    return $this->abcde->callB(); 
    }

    public function run()
    {

    } 
};

....

final call al method

$rightClass = new class($abOverride)
{
    public function __construct(abstractCommonAbcdef $abcommonABCDEF) 
    {
        $this->abcommonABCDEF = $abcommonABCDEF; 
    }

    public function getBo() {
        return $this->abcommonABCDEF;
    }
};


echo $rightClass->getBo()->callA(); 
echo $rightClass->getBo()->callB(); 
echo $rightClass->getBo()->callC(); 
echo $rightClass->getBo()->callD();
5
  • 1
    $class is a apparently a reference to an object, not the name of a class. I think it would be good to rename it to $object.
    – bdsl
    May 20, 2018 at 13:18
  • Can you add an interface implementation to classAB, classCD and classEF or is there a reason you want to avoid editing them?
    – bdsl
    May 20, 2018 at 13:19
  • You cannot change the classes, it calls for a virtual method though. May 20, 2018 at 13:28
  • @bdsl technical problem, too long to explain... May 20, 2018 at 13:31
  • If these ABC methods don't take parameters it should be easy to wrap the response from $repository into common interface (repository itself can implement some contract this way) - even with single method. Parameters change everything. Anyway, I wouldn't expect detailed answer here, because while concrete problem might have abstract solution (many implementations that lead to expected outcome), concrete solution to abstract problem does not exist.
    – shudder
    May 21, 2018 at 12:46

1 Answer 1

9

You can make a new interface and have all three classes implement it.

Each one will implement the same method but with a different implementation.

The switch statement can then be replaced with a call to that method.

Martin Fowler calls this refactoring Replace Conditional With Polymorphism. In his example he introduces an abstract superclass rather than an interface. It could work either way, but I tend to prefer interfaces.

3
  • I also thought this solution I like it. other ideas ? May 20, 2018 at 13:00
  • @ CandiedOrange right! done! May 20, 2018 at 13:17
  • @BruceStackOverFlow thank you. Now please delete these comments that are no longer meaningful because of the edit. May 20, 2018 at 13:20

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.