Dependency injection 如何在symfony3中注入接口(而不是类)?

Dependency injection 如何在symfony3中注入接口(而不是类)?,dependency-injection,interface,symfony,Dependency Injection,Interface,Symfony,我对Symfony DependencyInjection组件有问题。我想将接口注入控制器,因此只能使用接口方法。但是,我注意到我可以使用类中实现接口的任何公共方法,这是错误的。我关注这篇伟大的文章: 编写测试服务类和接口 interface ITestService { public function interfaceFunction(); } class TestService implements ITestService { public function inter

我对Symfony DependencyInjection组件有问题。我想将接口注入控制器,因此只能使用接口方法。但是,我注意到我可以使用类中实现接口的任何公共方法,这是错误的。我关注这篇伟大的文章:

编写测试服务类和接口

interface ITestService
{
    public function interfaceFunction();
}

class TestService implements ITestService
{
    public function interfaceFunction() {/* do somenthing */}

    public function classFunction() {/*do somenthing*/}
}
# file: app/config/services.yml
test_service:
    class: MyApp\Application\Services\TestService
将我的应用程序服务类配置为服务(测试服务)

将我的控制器配置为服务:

# file: app/config/services.yml
test_controller:
    class: MyApp\AppBundle\Controller\TestController
    arguments:
        - '@test_service'
在控制器中使用服务

class TestController extends Controller
{
    private testService;

    function _construct(ITestService $testService)
    {
        $this->testService = $testService;
    }

    public function indexAction()
    {
        // This should be inaccesible but it works :(
        $this->testService->classFunction();

        // This is the only function I should use.
        $this->testService->interfaceFunction();
    }
这是因为尽管有类型提示,PHP直到运行时才计算要调用的方法。这可能被认为是不可取的,但它允许使用一些技术,例如

这里有一个基于您提供的示例的简化示例(它没有将Symfony容器放入混合中,因为这纯粹与PHP有关)。你可以:

输出:

ServiceWithOtherFunction interfaceFunction
ServiceWithOtherFunction otherFunction
ServiceWithoutOtherFunction interfaceFunction

Fatal error: Uncaught Error: Call to undefined method ServiceWithoutOtherFunction::otherFunction() in /in/mZcRq:28
Stack trace:
#0 /in/mZcRq(43): Controller->indexAction()
#1 {main}
  thrown in /in/mZcRq on line 28

Process exited with code 255.
但是当我们注入另一个不包含
otherFunction
的实现时,代码在运行时抛出一个
错误

final class ServiceWithoutOtherFunction implements IService
{
    public function interfaceFunction() { echo "ServiceWithoutOtherFunction interfaceFunction\n"; }
}

$controllerWithoutOtherFunction = new Controller(new ServiceWithoutOtherFunction);

$controllerWithoutOtherFunction->indexAction();
输出:

ServiceWithOtherFunction interfaceFunction
ServiceWithOtherFunction otherFunction
ServiceWithoutOtherFunction interfaceFunction

Fatal error: Uncaught Error: Call to undefined method ServiceWithoutOtherFunction::otherFunction() in /in/mZcRq:28
Stack trace:
#0 /in/mZcRq(43): Controller->indexAction()
#1 {main}
  thrown in /in/mZcRq on line 28

Process exited with code 255.

如果要使用接口、DI和DIC,则不应调用任何公共方法,而应调用接口公开的方法。这是真正利用接口好处的唯一方法:与实现细节分离,并且能够在不更改
控制器内部任何内容的情况下更改要注入的类

我认为
OOP
中不存在这样的概念。你可以试着玩弄
trait
s,但既然这些不是可供选择的类型,为什么它不可访问呢
$testService
仍然是类
testService
的一个对象,该类没有实现一些接口。谢谢,@JovanPerovic和yoshi。嗯,在我的构造函数中,我正在等待一个具有ITestService契约的对象。我应该放弃本合同中不存在的任何方法。我使用c#和castle windsor IoC框架,我只能使用界面中定义的方法。这对我来说是有意义的,但symfony组件让我感到困惑。这是一个PHP问题。只是接口和对象的实现方式。IDE至少应该阻止您使用非接口方法。PHP解析要在运行时调用的方法。您不需要明确的对象类,例如java或C++。事实上,您根本不需要指定类型提示:方法可以很好地工作。类型提示是运行时检查、方法签名的契约。