Pieter Goosen
Pieter Goosen

Reputation: 9941

Inject any of four classes into a class

I have a class (lets call it TestClassA) in which the constructor looks something like this

public function __constructor(SomeInterface $some, AnotherInterface $another, $additionalArgs = null)
{
    // Rest of code
}

The value of $additionalArgs can come from any of four unique classes. Each of these classes will add unique query arguments to the class above according to the user's condition set. Lets name these classes

I'm not sure if interface injection will be my best solution here, as, once a condition is set, it will most probably never change again, and only one option can be set at any given time. For example, if the user has decided to use TestC class, the probability that he will change to either of the other three remaining classes is almost zero. So, if I'm correct, if I use interface injection (like in the example below) and add all four classes, I will instantiate 3 classes unnecessarily as they will in most probability never get used

public function __constructor(
    SomeInterface $some, 
    AnotherInterface $another,
    TestBInterface $testB,
    TestCInterface $testC,
    TestDInterface $testD,
    TestEInterface $testE
) {
    // Rest of code
}

What I thought of was to create my TestClassA with a property of $additionalArgs, creating a new instance of the required class, lets say TestC and then passing that to the $additionalArgs, which I then use in a method to get the required values.

Example

$a = new SomeClass;
$b = new AnotherClass;
$c = new TestC;

$d = new TestClassA($a, $b, $c->someMethod());

My question is, how do I make sure that the value passed to $additionalArgs is a valid instance of one of the four classes that should be passed to this parameter. I have already tried to verify this using instanceof in my method, in this example someMethod() , but the condition fails

Any suggestions on how to address this problem, and still "comply" with basic OOP principles?

Upvotes: 1

Views: 48

Answers (1)

Styphon
Styphon

Reputation: 10447

Currently you're passing in the result of a method, you can't test that to see what class it came from so instanceof won't work. What you need to do is pass in the object, test that and then call the method. Try this:

class TestClassA() {
    $foo;
    $bar;
    $testB;
    $testC;
    $testD;
    $testE;
    public function __constructor(Foo $foo, Bar $bar, $test = null)
    {
        $this->foo = $foo;
        $this->bar = $bar;
        if ( ! is_null($test))
        {
            if ($test instanceof TestClassB)
            {
                $this->testB = $test->someMethod();
            }
            elseif ($test instanceof TestClassC)
            {
                $this->testC = $test->someMethod();
            }
            elseif ($test instanceof TestClassD)
            {
                $this->testD = $test->someMethod();
            }
            elseif ($test instanceof TestClassE)
            {
                $this->testE = $test->someMethod();
            }
            // Optional else to cover an invalid value in $test
            else
            {
                throw new Exception('Invalid value in $test');
            }
        }
        // Rest of code
    }
}

$a = new Foo;
$b = new Bar;
$c = new TestClassC;

$d = new TestClassA($a, $b, $c);

Upvotes: 1

Related Questions