请原谅这个问题的可能天真,但是我让自己真的很困惑。似乎最好使用依赖注入来解耦代码,以便您的类加载其依赖项。请想想以下类,其中Class Foo具有类Bar的依赖性
namespace Classes;
class Foo{
protected barInstance;
public function __construct(Bar $barInstance){
$this->barInstance=$barInstance;
}
}
但是,如果您正在自动加载您的课程,那么在不需要DI的情况下,以下内容完全相同吗?
namespace Classes;
use Classes/Bar;
class Foo{
protected barInstance;
public function __construct(){
$this->barInstance=new Bar;
}
}
感谢任何响应者。
答案 0 :(得分:3)
自动加载确保您在引用它时定义了类。依赖注入使您可以灵活地使用您使用的对象的实例。
在您的示例中,假设您的Bar
类管理数据库连接。并且假设您有时想要连接到不同的数据库。
public function __construct(){
$this->barInstance = new Bar();
}
现在,您必须重构Foo
课程以处理更改,因为您已将其与Bar
的实例紧密耦合。
public function __construct(Bar $barInstance){
$this->barInstance = $barInstance;
}
现在,在不更改Foo
的情况下,我可以针对不同情况实例化Bar
的不同实例。一个常用的例子是单元测试。
在这两种情况下,自动加载确保Bar
及其所有依赖项都在Foo
之外定义。
答案 1 :(得分:2)
以数据库连接为例。
你有
public class foo {
public function __construct(DbConnectionInterface $db) { ... }
}
public class foo2 {
public function __construct(DbConnectionInterface $db) { ... }
}
...
等等
在你的“服务容器”中你有类似的东西
$db = new PdoDbConnection(); // which implements DbConnectionInterface
$service['foo'] = new foo($db);
$service['foo2'] = new foo2($db);
如果明天你想使用除了pdo之外的其他东西,那么你只需要建立一个实现该接口的新连接,然后就可以在一个地方更改你的数据库连接
$db = new NotPdoDbConnection(); // which implements DbConnectionInterface
$service['foo'] = new foo($db);
$service['foo2'] = new foo2($db);
如果您没有使用DI,那么您应该使用此类将所有类中的新PdoConnection()更改为新的NotPdoConnection()。但在这种情况下,自动加载对你来说无济于事。正如lsklyut所说,他回答了两个不同的概念。
它是一个“虚拟”案例,但你可以阅读一些有关DI的有趣文章
http://fabien.potencier.org/what-is-dependency-injection.html http://www.martinfowler.com/articles/injection.html
答案 2 :(得分:0)
这是两个独立的概念。自动加载将允许您不必在脚本中包含文件,并允许您按概念分隔您的类。就依赖注入而言,如果Bar有额外的依赖关系并且不能简单地通过使用新的Bar()来实例化,而是使用新的Bar($ dep1,$ dep2),那么创建Bar的逻辑将被隐藏在Foo的构造函数中,如以及需要Bar的任何其他类的构造函数。通过在注入之前反转创建Bar的依赖关系,你可以减轻Foo的额外责任。
答案 3 :(得分:0)
自动加载和依赖注入是无关的概念。
自动加载器知道如何加载类。当像new Foo()
这样的简单语句运行时,解释器需要知道Foo
类的定义。如果它还不知道它,那么它会调用自动加载器,直到该类可用。自动加载器知道每个类的定义位置并包含正确的文件。
依赖注入容器知道如何构建各种类型的对象。关于类加载它不知道(也不关心)。它假设当它运行new Bar()
时,已经定义了类Bar
(或者它可以被自动加载)。