Smalltalk和Java中的OO之间的主要区别是什么?
Smalltalk和Java中的OO之间的主要区别是什么?
请注意,我是一名Java程序员,试图通过探索Smalltalk来拓展自己的视野。 目前我对Smalltalk几乎一无所知,只是比Java更纯粹。 因此,我更喜欢这样的答案,它显示了各种Java概念如何映射到相应的Smalltalk概念,然后引入了根本不存在于Java中的Smalltalk概念。
消息传递
Smalltalk使用消息传递,而不是方法调用。 区别是微妙的,但是非常强大。
一些术语:给定foo bar: baz
, #bar:
是一个select器 ,foo是一个名为#bar:
的消息的#bar:
(#表示一个符号,就像Common Lisp会说'bar
(甚至更适合:bar
)),而baz
是一个参数或参数 。 当行被执行时, foo
被发送消息#:bar:
带有参数baz
。 到目前为止,这是非常正常的。 在Java中它看起来像foo.bar(baz);
。
在Java中,运行时系统会找出foo
的实际types,find最合适的方法并运行它。
事情在Smalltalk中看起来几乎一样。 向对象发送消息时,会在其方法字典中search名称与消息select器的名称匹配的方法。 如果找不到,则在其超类的方法字典中search,等等。 很正常的东西。
如果找不到任何匹配的方法,则将自身发送#doesNotUnderstand:
消息,并将原始消息作为参数。 (是的,一个消息发送是一个对象。)但是#doesNotUnderstand:
也只是一个方法。 你可以覆盖它。
例如,您可以让一个对象响应某些消息,同时将其收到的任何其他消息转发给某个委托对象。 覆盖#doesNotUnderstand:
嘿presto,你有一个代理,将不需要维护,以保持其协议与委托同步。
平凡的语法
不,我不是在开玩笑。 Smalltalk的整个语法可能有15行。 JLS是…不是。 为什么要关心 一个简单的语法可以简单地将一大块代码分开。 元编程! 重构!
没有语法:
- 条件语句:
(n < 3) ifTrue: ['yes'] ifFalse: ['no']
- for循环:
1 to: 10 do: [:i | Transcript show: i asString]
1 to: 10 do: [:i | Transcript show: i asString]
- try-catch:
[i := i / 0] ifError: ['oops!']
- try-finally:
[i := i / 0] ensure: [stream close]
并注意所有这些使用简洁的语法的一stream的closures。
Java和Smalltalk之间的一个主要区别是,Smalltalk具有一stream的类(没有双关语意思)。
Smalltalk中的一个类是一个对象。 最接近static
方法和variables的就是类方法和variables,正如弗兰克·希勒所说的那样。
但是,只要inheritance被使用,这种差异就会更加深刻。 在java类中,inheritance不存在,而在Smalltalk中是可能的。
如果类A
inheritance自B
,并且如果您有a
和b
,它们是A
和B
实例,则在Smalltalk中, b class
inheritance自a class
。 在Java中, a getClass()
和b getClass()
返回Class
实例并不相互关联。
现在让我们假设类A
实现了单例模式:它有一个类方面的字段instance
和一个getter方法instance
。 B
类是另一个有自己的instance
字段的对象。 因此, A instance
和B instance
将返回不同的对象。
从面向对象的angular度来看,这显然是Smalltalk和Java之间的主要区别之一。
其他的不同之处还包括元类的存在,扩展方法,鸭子打字与静态打字, doesNotUnderstand
具体化以及其他一些使Smalltalk或Java完全不同的编码的东西。
当然,Smalltalk已经closures了,Java仍然缺less。
另请参见Java为什么不允许重写静态方法?
- 对象模型。 在Smalltalk中,每件事物都是一个对象。 Java具有像int和float这样的基本types,其performanceforms和行为与复杂对象不同。
- 行为调用。 通过发送消息来调用Smalltalk对象的行为。 Java有方法,基本上是函数调用,目标对象是一个特殊的第一个参数,称为
this
。 - 封装。 Smalltalk有严格的封装。 对象的字段只能通过消息显示。 相比之下,Java允许公共领域。
- 活力。 Smalltalk是非常有活力的。 所有types在运行时被识别。 一个类可以在运行时被内省和修改(dynamic元编程!)。 新类可以在运行时创build和实例化。 Java具有静态types检查以及运行时多态性。 有反省和思考,但类和对象不能从正在运行的程序中修改。
- 句法。 Smalltalk没有语法。 相反,它具有发送消息的简单,一致的格式。 和C语言的其他语言一样,Java语法也很复杂。
- 环境。 大多数Smalltalk实现提供了一个完整的,独立的,实时计算环境和基于图像的持久性 。 其中一些环境甚至可以在裸机上启动 。 JVM反过来通常依赖于底层操作系统的线程,networking等。源代码必须input到文本文件中,编译并显式加载到JVM中执行。
试图通过探索Smalltalk来拓展自己的视野
如果您正在积极尝试探索Smalltalk,那么您需要知道如何阅读Smalltalk –
“我可以读取C + +和Java,但我不能读取Smalltalk”pdf
在Smalltalk中,一切都是对象,而在Java中,像小整数这样的东西仍然不是第一类对象。 另外,为了继续使用数字,Smalltalk由于其纯粹的OO特性和强大的reflection能力,我们从不需要关心数字的大小,就像整数大小一样,当小整数溢出时会发生什么。
Java中不存在的一个Smalltalk概念是近年来越来越stream行的一个概念。 块是一种匿名函数的forms,包括它们被定义的上下文。重要的是,块也是对象。 Smalltalk实际上缺less任何types的内置if
语句或for
-loop或类似的东西,但是只是通过消息传递和块来设法产生相同的效果。
object isBig ifTrue: [self runIntoObject:object] ifFalse: [self katamariBall absorbObject:object]. 1 to: 10 do: [:number | number print]
当@JankoMivšek表示一切,他真的是一切。 🙂
即使是发送消息,你正在做的是创build一个上下文的对象。
另外,你在Smalltalk中没有的是访问修饰符(private / protected / public)。你在一些Smalltalk实现中没有包,而且在大多数Smalltalk实现包中没有与Java相同的语义。
在smalltalk中,如果尝试/抓住,你没有控制结构。很酷的事情是,你不需要它们,因为你有小块封锁。
在smalltalk中,你没有静态成员,而是你有对象的类(你可以发送消息到类,你也可以把类放入一个variables)。
在smalltalk你没有嵌套的类。
…