是的,确实有。有点。
Newspeak没有静态,也没有全局。这意味着访问依赖项的唯一可能方法是显式注入依赖项。显然,这意味着该语言,或更准确地说,对于Newspeak,IDE 需要使依赖注入变得容易,否则该语言将无法使用。
因此,语言不是为DI设计的,而是DI的必要性是语言设计的结果。
如果没有静态状态,也没有全局状态,那么您不能仅仅“伸出”手以太并拔出某些东西。例如,在Java中,包结构是静态的。我可以说java.lang.String
,我自己String
上课。这在Newspeak中是不可能的。您使用的所有内容都必须明确提供给您,否则您将无法使用。因此,所有都是依赖,每个依赖都是显式的。
你想要一个字符串吗?好吧,您必须首先要求stdlib
对象将String
课程交给您。哦,但是您如何访问stdlib
?好吧,您必须首先要求platform
将stdlib
物件交给您。哦,但是您如何访问platform
?好吧,您必须首先请别人将platform
物体交给您。哦,可是您如何联系那个人呢?好吧,您必须首先请另一个人将您的物品交给您。
这会走到兔子洞多远?递归在哪里停止?一路走,实际上。它并没有停止。那么,如何在Newspeak中编写程序?好吧,严格来说,你不能!
您需要一些外部实体将它们联系在一起。在Newspeak中,该实体是IDE。IDE会看到整个程序。它可以将不同的部分连接在一起。Newspeak的标准模式是您的应用程序的中心类有一个名为的访问器platform
,Newspeak IDE将一个对象注入该访问器,该对象具有的方法可以返回一些编程的基本需求:一个String
类,一个Number
类,一个Array
类,等等。
如果要测试您的应用程序,则可以注入一个platform
对象,该对象的File
方法返回带有伪方法的类。如果您想将应用程序部署到云中,请注入一个平台,该平台的File
类实际上由Amazon S3支持。跨平台的GUI通过为不同的OS注入不同的GUI框架来工作。Newspeak甚至具有实验性的Newspeak-to-ECMAScript编译器和HTML支持的GUI框架,通过注入不同的GUI元素,您无需更改即可将功能齐全的GUI应用程序从本机桌面移植到浏览器中。
如果要部署应用程序,IDE可以将应用程序序列化为磁盘对象。(不像它的祖先,Smalltalk中,新话有出的图像的对象序列化格式,您不必采取整个图像用你,正是因为所有依赖注入:在IDE知道究竟该系统应用程序的部分因此,它精确地序列化了组成应用程序的对象空间的连接子图,仅此而已。)
所有这些简单地通过将面向对象的方法发挥到极致:一切都是虚拟方法调用(Smalltalk术语中的“消息发送”,Newspeak是其后代)。甚至超类查询也是一个虚拟方法调用!采取类似
class Foo extends Bar // using Java syntax for familiarity
或者,在Newspeak中:
class Foo = Bar () () : ()
在Java中,这将Foo
在静态全局名称空间中创建一个名称,并Bar
在静态全局名称空间中进行查找,并使其成为Bar
Foo
超类。即使在动态性更高的Ruby中,它仍将在全局名称空间中创建一个静态常量。
在Newspeak中,等效声明意味着:创建一个名为的getter方法,Foo
并通过调用名为的方法使它返回一个查找其超类的类Bar
。注意:这与Ruby不同,您可以在其中放置任何可执行的Ruby代码作为超类声明,但是该代码仅在创建类时执行一次,并且该代码的返回值成为固定的超类。否。每次查找单个方法都会Bar
调用该方法!
这具有深远的意义:
- 因为mixin基本上是尚不知道其超类的类,并且在Newspeak中,超类是动态的虚拟方法调用,因此未知,每个类自动也是mixin。您可以免费获得mixins。
由于内部类只是返回一个类的方法调用,因此您可以在外部类的子类中覆盖该方法,因此每个类都是虚拟的。您可以免费获得虚拟类:
class Outer {
class Inner { /* … */ }
}
class Sub extends Outer {
override class Inner { /* … */ }
}
新闻发言人:
class Outer = () (
class Inner = () () : ()
) : ()
class Sub = Outer () (
class Inner = () () : ()
) : ()
由于超类只是一个返回类的方法调用,因此您可以在外部类的子类中覆盖该方法,因此在超类中定义的内部类在子类中可以具有不同的超类。您可以免费获得类层次结构继承:
class Outer {
class MyCoolArray extends Array { /* … */ }
}
class Sub extends Outer {
override class Array { /* … */ }
// Now, for instances of `Sub`, `MyCoolArray` has a different superclass
// than for instances of `Outer`!!!
}
新闻发言人:
class Outer = () (
class MyCoolArray = Array () () : ()
) : ()
class Sub = Outer () (
class Array = () () : ()
) : ()
最后,对于本次讨论而言,最重要的是:由于(显然,除了您在类中定义的那些),您只能在词汇上封闭的类和父类(最顶层的最外层类)中调用方法不能调用任何方法都只是明确注入的:一个顶级类不具有封闭类,它的方法也可以打电话,也不能有非默认的其他超类,因为超类声明是一个方法调用,它显然不能转到超类(它是父类),它也不能进入词汇上封闭的类,因为没有任何类。这意味着顶级类被完全封装,它们只能访问它们显式注入的内容,而它们仅被注入显式要求的内容。换句话说:顶级类是模块。您可以免费获得整个模块系统。实际上,更准确地说:顶级类是模块声明,其实例是模块。因此,您将免费获得带有参数化模块声明和一流模块的模块系统,这是许多甚至非常复杂的模块系统都无法做到的。
为了使所有这些注入变得轻松,类声明具有不寻常的结构:它们由两个声明组成。一个是类构造函数,它不是构造类实例的构造函数,而是构造类主体运行环境的构造函数。用类似Java的语法,看起来像这样:
class Foo(platform) extends Bar {
Array = platform.collections.Array
String = platform.lang.String
File = platform.io.File
| // separator between class constructor and class body
class MyArray extends Array { /* … */ }
// Array refers to the method defined above which in turn gets it from the
// platform object that was passed into the class "somehow"
}
新闻发言人:
class Foo using: platform = Bar (
Array = platform collections Array
String = platform streams String
File = platform files ExternalReadWriteStream
) (
class MyArray = Array () () : ()
) : ()
请注意,Newspeak程序员实际查看类的方式是这样的:
不过,我什至无法开始这样做。您必须自己玩。吉拉德·布拉查(Gilad Bracha)就系统的各个方面(包括模块化)进行了几次演讲。他进行了很长时间的演讲(2小时),其中的第一小时是对语言的全面介绍,包括模块化的故事。Newspeak编程平台的第2章介绍了模块化。如果您在Squeak上浏览Newspeak –《困惑的指南》(又名Newspeak-101),就会对系统有所了解。Newspeak by Example是一个实时文档(例如,它在ECMASCript的Newspeak上运行,每行代码都是可编辑的,每个结果都是可检查的),展示了基本语法。
但实际上,您必须尝试一下。它与所有主流甚至大多数非主流语言都有很大的不同,以至于难以解释,必须要有经验。