为什么Java需要接口而Smalltalk不需要?

为什么Java需要接口而Smalltalk不需要?,java,interface,smalltalk,Java,Interface,Smalltalk,我用Smalltalk编程已经有一段时间了,但我从来没有真正需要接口来实现任何东西。那么为什么像Java这样的语言不能摆脱接口呢?这只是Smalltalk,还是有另一种语言不需要接口?不确定你到底在问什么(或者更确切地说,你最想回答哪个问题),但看看Ruby。据我所知,它比Java更接近smalltalk 如果我要回答为什么java需要接口的问题,我想我会说一些关于java是一种静态类型语言的东西,并且把这种哲学带到java需要接口的程度。实际上,接口试图在java中提供类似多重继承的功能,而不

我用Smalltalk编程已经有一段时间了,但我从来没有真正需要接口来实现任何东西。那么为什么像Java这样的语言不能摆脱接口呢?这只是Smalltalk,还是有另一种语言不需要接口?

不确定你到底在问什么(或者更确切地说,你最想回答哪个问题),但看看Ruby。据我所知,它比Java更接近smalltalk


如果我要回答为什么java需要接口的问题,我想我会说一些关于java是一种静态类型语言的东西,并且把这种哲学带到java需要接口的程度。实际上,接口试图在java中提供类似多重继承的功能,而不存在其他语言(我相信C++)所面临的多重继承问题。

因为java是静态类型的,而Smalltalk不是。当您不声明类型并且您的变量不进行类型检查时,接口就没有任何用途。但是在像Java这样的静态类型语言中,它们非常方便,因为它们让您拥有一个变量,其类型由对象实现的方法而不是其类定义。它使您更接近Smalltalk本机提供的动态类型,而不放弃类型检查的好处。

这是一个多态性问题:在Java中,您有静态类型,因此您需要知道您的对象可以回答哪些消息。。。在Smalltalk(和其他非静态语言)中,您只需要实现正确的方法就可以实现多态性

例如:

  • 在Java中,您需要实现Cloneable,这是谁定义的方法 Cloneable.clone具有可克隆对象。然后,编译器就知道了 您的对象将理解该方法(否则它将抛出 (错误)
  • 在smalltalk中,您只需要实现方法克隆。 编译器从不知道/不关心哪些消息理解您的 对象,直到调用它为止
这也意味着您可以拥有多态对象,而不必成为同一层次结构的一部分。。。多重继承、混合和其他方法(特性出现在Pharo上)只是重用技术,而不是设计约束


这种做事方式通常被称为“鸭子打字”。。。请参阅:

您认为Smalltalk中的“接口”可能有一个有用的角色吗


请参阅-

Java不需要接口。编译器选择支持而不是放弃它

在运行时,接口不能用任何语言强制执行,因为所有动态对象都是1。纯状态或2的结构。纯状态的结构,第一个成员是指向vtable映射的指针,该vtable映射可以是整数到成员(通过数组)或字符串到成员(字典/哈希映射)。这样做的结果是,您可以始终更改vtable索引处的值或hashmap条目,或者只更改指向另一个vtable地址的vtable指针,或者只是非法访问内存

Smalltalk可以很容易地存储在类编译时提供的信息,在某种程度上,Smalltalk浏览器中的intellisense就是这样为成员提供建议的,但这实际上对Smalltalk没有好处

smalltalk的语法有几个问题限制了接口的使用


  • Smalltalk只有一种主要类型
  • 这意味着,如果你尝试将一个正方形放入一个圆形孔中,它不能仅仅警告你,没有正方形,没有孔,所有东西都是smalltalk编译器的对象

    编译器可以选择类型推断分配的变量,但smalltalk哲学上反对这样做


  • Smalltalk方法总是使用一个参数
  • 这可能看起来像是在:1 put:hi:myArray有两个参数,但实际上,您调用的是myArray['at:put:']([1,'hi'])的javascript等价元素,myArray是一个对象(~hashmap)。因此,如果不打破smalltalk的哲学,就无法检查争论的数量

    smalltalk可以做一些变通方法来检查参数的数量,但它不会带来太多好处


  • smalltalk将其编译器公开给运行时,而java则努力从运行时隐藏编译器
  • 当您将编译器暴露为运行时(从汇编到JavaScript的所有语言都可以很容易地将编译器暴露到运行时,很少有人将它作为语言的易访问部分的一部分,编译器在运行时越容易访问,我们认为语言越高)。您的语言变得更加脆弱,因为您在编译时在一行上使用的信息在另一行上可能不再有效,因为在运行时,编译器所依赖的修复信息不再相同

    这样做的一个结果是,一个类可能在程序的某个点上有一个接口,但在程序运行到一半时,用户将该类更改为有另一个接口;如果用户希望在编译时使用此接口(在使用代码更改类之后),编译器需要更加智能地认识到不支持“.Greet()”的类现在突然支持,或者不再支持,或者“.Greet()方法”和“.Foo()方法”已经交换

    接口在编译时很好,但在运行时完全不可执行。对于那些希望在不需要重新启动程序的情况下更改代码行为的人来说,这是一个好消息,对于类型安全纯粹主义者来说,这是一个可怕的消息——如果不在一段时间内手动插入每个断言,他们的理想就无法在运行时得到实施


    不同于C++,SimalTalk不为VTABLE使用数组,而是使用从字符串到对象的映射。这意味着,即使您确实知道该方法存在于您正在调用的类中,也无法将其优化为dispid,以便将来对该方法的调用使用数组偏移量而不是数组偏移量