What are the key differences between OO in Smalltalk and Java?
Please note that I am a Java programmer trying to expand his horizons by exploring Smalltalk. Currently I
trying to expand his horizons by exploring Smalltalk
If you are actively trying to explore Smalltalk then you need to know how to read Smalltalk -
"I Can Read C++ and Java But I Can’t Read Smalltalk" pdf
When @Janko Mivšek mean everything he really mean everything. :)
Even up to message send, what your are doing is creating an object that is the context.
Also what you don't have in smalltalk is access modifier (private/ protected / public) You don't have package in some Smalltalk implementation and in most Smalltalk implementation package don't have the same semantic than Java.
In smalltalk you don't have control structure like for, if, try/catch... The cool things is that you don't need them because you have block closure in smalltalk.
In smalltalk you don't have static member instead you have Class that are object(you can send message to class, you also can hold class in a variable).
In smalltalk you don't have nested class.
...
Smalltalk uses message passing, not method invocation. The distinction is subtle, but enormously powerful.
Some terminology: Given foo bar: baz
, #bar:
is a selector, foo is the receiver of a message called #bar:
(the # indicates a symbol, much like Common Lisp would say 'bar
(or even more appropriately, :bar
)), and baz
is an argument or parameter. When the line's executed, foo
is sent the message #:bar:
with argument baz
. So far, it's pretty normal. In Java it would look like foo.bar(baz);
.
In Java, the runtime system would figure out foo
's actual type, find the most appropriate method, and run it.
Things look almost the same in Smalltalk. When you send an object a message, it searches in its method dictionary for a method whose name matches that of the selector of the message. If it can't find one, it searches in its superclass' method dictionary, and so on. Pretty normal stuff.
If it can't find any matching method, it sends itself the #doesNotUnderstand:
message, with the original message as a parameter. (Yes, a message send is an object.) But #doesNotUnderstand:
is also just a method. You can override it.
For instance, you can have an object that responds to some set of messages while forwarding any other messages it receives to some delegate object. Override #doesNotUnderstand:
and hey presto, you have a proxy that will need no maintenance to keep its protocol in sync with the delegate.
No, I'm not joking. Smalltalk's entire grammar's maybe 15 lines long. The JLS is... not. Why care? A simple syntax makes it simple to tear a chunk of code apart. Metaprogramming! Refactoring!
No syntax for:
(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]
And notice all those []
s - first-class closures with a clean syntax.
A key difference between Java and Smalltalk is that Smalltalk has first-class class (no pun intended).
A class in Smalltalk is an object. The closest thing to static
method and variable is then class-side method and variable, as mentioned by Frank Shearer.
But this difference is more profound as soon as inheritance is used. In java class-side inheritance does not exists, while it is possible in Smalltalk.
If class A
inherits from B
, and if you have a
and b
which are instances of A
and B
, in Smalltalk, b class
inherits from a class
. This would not be the case in Java where a getClass()
and b getClass()
return instances of Class
, which are not related with each other.
Let's say now that class A
implements the singleton pattern: it has a class-side field instance
and an getter method instance
. Class B
is another object with its own instance
field. As a consequence, A instance
and B instance
will return different object.
This is clearly one of the major difference between Smalltalk and Java from a OO standpoint.
Other difference include the existence of metaclasses, extension methods, duck typing vs static typing, reification of doesNotUnderstand
and few other things that make coding in Smalltalk or Java completely different.
And of course, Smalltalk has closure which Java still lacks.
See also Why doesn’t Java allow overriding of static methods ?
One Smalltalk concept that doesn't exist in Java but has become increasingly popular in recent years is blocks. Blocks are a form of anonymous functions that include the context they were defined in. Importantly, blocks are also objects. Smalltalk actually lacked any kind of built-in if
-statement or for
-loop or anything like that, but managed to create the same effect just with message-passing and blocks.
object isBig ifTrue: [self runIntoObject:object]
ifFalse: [self katamariBall absorbObject:object].
1 to: 10 do: [:number | number print]
this
.