For dependency injection, I understand that I have to pass an instance of one class to the main instance instead of the main class creating it's own instance, like so (php):
class Class_One {
protected $_other;
public function setOtherClass( An_Interface $other_class ) {
$this->_other_class = $other_class;
}
public function doWhateverYouHaveToDoWithTheOtherClass() {
$this->_other_class->doYourThing();
}
}
interface An_Interface {
public function doYourThing();
}
class Class_Two implements An_Interface {
public function doYourThing() { }
}
class Class_Three implements An_Interface {
public function doYourThing() { }
}
// Implementation:
$class_one = new Class_One();
$class_two = new Class_Two();
$class_three = new Class_Three();
$class_one->setOtherClass( $class_two );
$class_one->doWhateverYouHaveToDoWithTheOtherClass();
$class_one->setOtherClass( $class_three );
$class_one->doWhateverYouHaveToDoWithTheOtherClass();
This is all fine. I know that since both Class_Two and Class_Three both implement An_Interface, they can be used interchangeably in Class_One. Class_One wouldn't know the difference between them.
My question is, is it ever a good idea to, instead of passing an instance to setOtherClass, pass a string such as "Class_Two", and have Class_One's setOtherClass method actually create the instance itself like so:
class Class_One {
...
public function setOtherClass( $other_class_name ) {
$this->_other_class = new $other_class_name();
}
...
}
Does this sort of defeat the purpose of Dependency Injection, or is this completely valid? I thought this type of set up may help me with configuration, where a user can specify which class he wants to use in a string earlier on and this can later be passed to the Class_One..
Actually, writing this out has made me think that it's probably not a good solution, but I'll still post this in case someone can give me some good feedback on why I should/shouldn't do this.
Thanks =)
Ryan
That theoretically defeats the purpose of dependency injection; you are telling Class_One, which depends on An_Interface, which concrete implementation of that interface it should instantiate. That requires Class_One to know how to instantiate ANY An_Interface implementation, tightly coupling Class_One to ALL An_Interface implementations. If you add a new An_Interface Class_Four, you have to go back and tell Class_One how to instantiate a Class_Four.
In PHP, you get away with this AS LONG AS all An_Interface implementations have a parameterless constructor. However, if any implementation needs OTHER dependencies injected, you're screwed; you can't tell Class_One to just new up a Class_Four if a Class_Four needs a Class_Five that Class_One doesn't know about.
Pass an object that's specified by an interface. Otherwise how will you always know with 100% accuracy what it will take to construct the object?
public function __construct(MyInterface $object) {
}
That way, it doesn't matter how you create the object, you just need to know if you can use it how you need to (the interface you're programming against)...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With