Smalltalk和Java中面向对象(OO)的主要区别是什么?
请注意,我是一名Java程序员,正在尝试通过探索Smalltalk来扩展自己的视野。目前,除了它比Java更加纯粹之外,我几乎不知道任何关于Smalltalk的知识。因此,我希望回答能够展示各种Java概念如何映射到相应的Smalltalk概念,并介绍在Java中不存在的Smalltalk概念。
Smalltalk和Java中面向对象(OO)的主要区别是什么?
请注意,我是一名Java程序员,正在尝试通过探索Smalltalk来扩展自己的视野。目前,除了它比Java更加纯粹之外,我几乎不知道任何关于Smalltalk的知识。因此,我希望回答能够展示各种Java概念如何映射到相应的Smalltalk概念,并介绍在Java中不存在的Smalltalk概念。
Smalltalk 使用消息传递,而不是方法调用。这种区别微妙但极为强大。
一些术语:给定 foo bar: baz
,#bar:
是一个 选择器,foo 是被称为 #bar:
的消息的 接收者(# 表示符号,就像 Common Lisp 会说 'bar
(或更合适的是 :bar
)),而 baz
是一个 参数 或 形参。当执行该行时,将发送带有参数 baz
的消息 #:bar:
给 foo
。到目前为止,这是相当正常的。在 Java 中,它看起来像 foo.bar(baz);
。
在 Java 中,运行时系统会确定 foo
的实际类型,找到最合适的方法并运行它。
在 Smalltalk 中,情况看起来 几乎 相同。当您向对象发送消息时,它会在其方法字典中搜索与消息选择器名称匹配的方法。如果找不到,则在其超类的方法字典中搜索,依此类推。非常正常的东西。
如果找不到任何匹配的方法,则将使用原始消息作为参数向自身发送 #doesNotUnderstand:
消息。(是的,消息发送也是一个对象。)但是,#doesNotUnderstand:
也只是一个方法。您可以覆盖它。
例如,您可以有一个对象,它响应某些消息,同时将其接收到的任何其他消息转发到某个委托对象。覆盖 #doesNotUnderstand:
,然后您就有了一个代理,无需维护即可保持其协议与委托同步。
不,我不是在开玩笑。Smalltalk的整个语法可能只有15行长。而Java语言规范(JLS)则不是这样的。为什么要关注呢?一个简单的语法使得分解一块代码变得简单。元编程!重构!
没有以下语法:
(n < 3) ifTrue: ['yes'] ifFalse: ['no']
1 to: 10 do: [:i | Transcript show: i asString]
[i := i / 0] ifError: ['oops!']
[i := i / 0] ensure: [stream close]
请注意所有的[]
- 具有干净语法的一流闭包。
this
。#doesNotUnderstand:
放在一边”可以改变很多事情。如果我们剪掉所有不同的东西,你不能指望别人认真对待你的话--当然,如果我们剪掉所有不同的东西,那当然会有相似之处。 :P - cHao#doesNotUnderstand
与“消息发送”无关。Python有类似的机制,但Python通过方法调用工作,就像Java一样。我不明白消息传递和方法调用之间的真正语义差异是什么,而这个答案并没有解释这一点。 - uhbif19doesNotUnderstand
)拦截消息,并且理想情况下,消息的发送者不知道或不关心是否发生了这种情况。您可以通过函数调用实现有限形式的“消息发送”,但是您会错过大部分好处。 - cHaoJava和Smalltalk之间的一个关键区别是,Smalltalk有一流的类(不是双关语)。
在Smalltalk中,类是一个对象。最接近static
方法和变量的东西是类侧的方法和变量,正如Frank Shearer所提到的那样。
但是,当继承被使用时,这种差异就更加深刻了。在Java中,类侧继承不存在,而在Smalltalk中是可能的。
如果类A
继承自B
,并且您有a
和b
是A
和B
的实例,在Smalltalk中,b class
继承自a class
。在Java中,这种情况并非如此,因为a getClass()
和b getClass()
返回的是Class
的实例,它们彼此之间没有关系。
A
实现了单例模式:它有一个类级别的字段 instance
和一个获取器方法 instance
。类 B
是另一个对象,有它自己的 instance
字段。因此,A instance
和 B instance
将返回不同的对象。doesNotUnderstand
的具象化和其他一些使得在Smalltalk或Java中编码完全不同的东西。通过探索Smalltalk来扩展自己的视野
如果您正在积极尝试探索Smalltalk,那么您需要知道如何阅读Smalltalk -
在IT技术领域,有一个在Java中不存在但近年来越来越流行的Smalltalk概念——blocks。Blocks是一种包含定义所在上下文的匿名函数,重要的是,blocks也是对象。实际上,Smalltalk缺乏任何内置的if
-语句、for
-循环或类似的东西,但通过消息传递和blocks,成功地实现了相同的效果。
object isBig ifTrue: [self runIntoObject:object]
ifFalse: [self katamariBall absorbObject:object].
1 to: 10 do: [:number | number print]
在Smalltalk中,一切皆为对象,而在Java中,像小整数这样的东西仍然不是一等公民对象。此外,继续谈论数字,在Smalltalk中,由于其纯面向对象的性质和强大的反射能力,我们永远不需要担心数字大小,例如整数是小型还是大型,以及当小整数溢出到大型时会发生什么。