Dependency injection 依赖注入作为一种语言特性?

Dependency injection 依赖注入作为一种语言特性?,dependency-injection,inversion-of-control,Dependency Injection,Inversion Of Control,是否有任何现有的现代编程语言明确地将依赖项注入作为一种语言功能,如果有,是否有任何示例说明此类编程语言如何使用其语法将程序依赖项从其具体实现中分离出来 (请注意:我不是在寻找DI/IOC框架——我实际上是在寻找一种在语言中内置了此功能的编程语言)。我无意听起来像个傻瓜,但每种OO语言都支持依赖注入。不需要特殊语法。只需使用它们的依赖项构造对象(或稍后设置它们的依赖项) 实际上,您可以将所有依赖项连接到程序顶部附近的某个位置—不一定是main(),而是靠近顶部。应该这样做,但我还没有看到语言规范(

是否有任何现有的现代编程语言明确地将依赖项注入作为一种语言功能,如果有,是否有任何示例说明此类编程语言如何使用其语法将程序依赖项从其具体实现中分离出来


(请注意:我不是在寻找DI/IOC框架——我实际上是在寻找一种在语言中内置了此功能的编程语言)。

我无意听起来像个傻瓜,但每种OO语言都支持依赖注入。不需要特殊语法。只需使用它们的依赖项构造对象(或稍后设置它们的依赖项)


实际上,您可以将所有依赖项连接到程序顶部附近的某个位置—不一定是
main()
,而是靠近顶部。

应该这样做,但我还没有看到语言规范(在找到它之前,我的耐心已经耗尽了)。

您不会发现依赖项注入是一种语言功能,因为它通常被视为一种设计模式。设计模式作为缺少语言功能的变通方法出现——例如,如果您将一类类型作为语言功能,则不需要factory模式(请参见的第12页),如果您将多个方法作为语言功能,则不需要double dispatch模式


DI作为设计模式的语言特征是“参数化模块”。参见与Gilad Bracha语言相关的vs DI

可以说Scala通过特征和自我类型注释的帮助,支持开箱即用的依赖注入。看看蛋糕图案:

基本上,这种方法使用具有声明依赖项的特性(通过使用自类型)让编译器将它们连接在一起

这是申报登记处:

object ComponentRegistry extends 
  UserServiceComponent with 
  UserRepositoryComponent 
{
  val userRepository = new UserRepository
  val userService = new UserService
}
…正在注册用户存储库:

trait UserRepositoryComponent {
  val userRepository: UserRepository

  class UserRepository {
    ...
  }
}
trait UserServiceComponent { 
  this: UserRepositoryComponent => 

  val userService: UserService  

  class UserService {
    ... 
  }
}
…以及依赖于存储库的用户服务组件:

trait UserRepositoryComponent {
  val userRepository: UserRepository

  class UserRepository {
    ...
  }
}
trait UserServiceComponent { 
  this: UserRepositoryComponent => 

  val userService: UserService  

  class UserService {
    ... 
  }
}

noop的注入方案将在上讨论,noop注入支持方案将基于Google的Guice注入框架。看来Noop是一种死语言。Noop语言论坛已经有很长一段时间没有任何活动了。另请参见关于“设计模式是编程语言中弱点的标志”的讨论——一些语言确实提供了服务定位器作为langauge特性。例如,python@Arafangion您是指import语句,还是该语言中的其他内容(与库相对)?拥有模块的搜索路径比服务位置少得多,依赖项注入并不等于服务位置。您可以在运行时(随时)更改模块的内容,这些更改将影响导入该模块的每个模块。这与告诉服务定位器“如果需要IFoo,请提供一个条,而不是通常的Foo”,“如果您有一流的类型作为语言功能,您不需要工厂模式”这一理论的任何示例或证明?我不是在寻找一种允许您实现依赖注入的编程语言,我实际上在寻找一种语言,它说“我想创建一个IFoo”,然后编译器/运行时决定创建什么,而不在编译时指定具体的类。啊,我想你在寻找对自动连接或自动服务发现的语言支持。我错了,你是说“控制反转”?你甚至不需要面向对象,只要把每个模块写成一个函子/工厂,然后在合成根中初始化它们,我想?“依赖注入”是指您不必手动(在您的大脑中编写代码)遍历依赖关系图并按正确的顺序初始化它们,相反,一些框架会为您找到答案。我想国际奥委会比直接投资更重要,直接投资只是一种方便的方式。然而,当您需要DI时,您的合成根可能会变得相当大。您所描述的通常称为“依赖注入框架”,即进行依赖注入的框架。但是手动依赖注入也是一件事。控制反转是一个更广泛的主题,它还包括事件回调等内容。看看这篇精彩的演讲,鲁纳尔超级聪明,也很搞笑:“控制权倒置,这真的只是一种自命不凡的表达‘争论’的方式。”