Are there philosophical differences between Smalltalk OOP and Simula OOP ?
This is a question related to Java & C# vs C++ indirectly. As I understand, C++ is based on Simula but Java and C# are more or less from the Smalltalk family.
Are there philosophical differences between Smalltalk OOP and Simula OOP ?
This is a question related to Java & C# vs C++ indirectly. As I understand, C++ is based on Simula but Java and C# are more or less from the Smalltalk family.
I'd put Java and C# in the Simula camp as well:
Smalltalk, being dynamically typed, is quite apart of the four other languages you cite.
Smalltalk is structurally typed (alias duck typing) while the other four are nominally typed.
(What Java and C# have in common with Smalltalk is being mainly based on a VM, but there is little influence on the programming style).
I would say statically typed and dynamically typed OOP are two separate disciplines within the same school of OOP.
Java, C#, and C++ all follow a similar OOP strategy. It is based on function calls that are bound at compile time. Depending ont he call, either the direct function call or an offset into a vtable is fixed when compilation happens. By contrast Smalltalk's OOP is based on message passing. Conceptually every method call is a message to the receiving object asking whether it has a method called "Foo."
Smalltalk has no concept of interfaces. It only has similar looking methods. In the C++ group of languages, everything is bound to interfaces. One cannot implement AddRef and Release without also implementing QueryInterface (even if it is just a stub) because they are all part of the IUnknown interface. In Smalltalk, there is no IUnknown. There is only a collection of 3 functions, any of which could be implemented or not.
Java and C# are definitely not from the Smalltalk family. Alan Kay even said that when he created OOP he did not have anything like Java or C++ in mind. Java, C#, and C++ all interpret OOP in pretty much the same way.
Languages like Smalltalk and Ruby have a radically different model that is based on message passing. In C++ classes are essentially namespaces for methods and state. Method invocations are bound at compile time. Smalltalk does not bind a "method call" until runtime. The result of this is that in C++
foo->bar
is compiled to mean "call the bar method on the foo object." If bar is non virtual, I'd imagine that the address of the bar method is specifically referenced.
In Smalltalk
foo bar
means "send the message bar to the foo object." foo
can do whatever it wants with this message when it arrives. The default behavior is to call the method named bar
, but that is not required. This property is exploited in Ruby for ActiveRecord column accessors. When you have an ActiveRecord object and you send it the name of a column in its database table as a message, if there is no method with that name defined, it checks to see if there is a column by that name on the table and if there is returns the value.
Message passing might seem like a tiny, irrelevant detail, but out of it, the rest of OOP easily flows.
"OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things. It can be done in Smalltalk and in LISP. There are possibly other systems in which this is possible, but I'm not aware of them." -- Alan Kay, creator of Smalltalk
Eiffel is a statically typed, compiled, multiple inheritance pure OOP language.
Of the modern (and I use the term lightly) OO programming languages Objective C is the most like smalltalk.
In C++,C# and Java: messages are bound at compile time.
You can think of a method call as a message being sent to the object.
In Objective C,Smalltalk: messages are bound at run time.
I'd say there is also a pretty big difference, conceptually, between class-based OOP (of which Smalltalk, Simula, C# and Java are all examples) and prototype-based OOP (which started with Self and is most widespread in JavaScript).
Several key 'differences in 'Style' within the broader OOP banner.
In all cases a statement about a static or dynamic type system means predominately one or the other, the issue is far from clear cut or clearly defined. Also many languages choose the blur the line between the choices so this is not a list of binary choices by any means.
or "what does foo.Bar(x)
mean?"
1 is often used within statically typed frameworks where it is an error, checked at compile time for no such implementation to exist. Further the languages often differentiate between Bar(x) and Bar(y) if x and y are different types. This is method overloading and the resulting methods with the same name are viewed as entirely different.
2 is often used in dynamic languages (which tend to avoid method overloading) as such it is possible that, at runtime the type of foo has no 'handler' for the message named 'Bar', different languages handle this in different ways.
Both can be implemented behind the scenes in the same fashion if desired (often the default for the second, Smalltalk style is to invoke a function but this is not made a defined behaviour in all cases). Since the former method can frequently be easily implemented as simple pointer offset function calls it can, more easily, be made relatively fast. This does not mean that the other styles cannot also be made fast, but more work may be required to ensure that the greater flexibility is not compromised when doing so.
or "Where do babies come from?"
Again 1 tends to happen in static languages, 2 in dynamic though this is by no means a requirement they simply lend themselves to the style.
or "what or how?"
This is very much not a binary choice. Most class based languages allow the concept of abstract methods (ones with no implementation yet). If you have a class where all methods are abstract (called pure virtual in C++) then what the class amounts to is pretty much an interface, albeit one that may have also defined some state (fields). An true Interface should have no state (since it defines only what is possible, not how it happens.
Only older OOP languages tend to rely solely on one or the other.
VB6 has only on interfaces and have no implementation inheritance.
Simula let you declare pure virtual classes but you could instantiate them (with runtime errors on use)
or "Who is the daddy?"
This question provokes considerable debate, especially as it is a key differentiator between C++'s OOP implementation and many of the modern statically typed languages perceived as possible successors like c# and java.
or "what do you want to do to me?"
Frequently this is not an all or nothing it is simply a default (most commonly used OOP languages default to mutable by default). This can have a great deal of affect on how the language is structured. Many primarily functional languages which have included OOP features default the objects to have immutable state.
or "Is everything an Object?"
This is quite complex since techniques like auto boxing of primitives make it seem like everything is but you will find that several boundary cases exist where this 'compiler magic' is discovered and the proverbial wizard of Oz is found behind the curtain resulting is problems or errors. In languages with immutability as a default this is less likely to happen, since the key aspect of objects (that they contain both methods and state) means that things that are similar to objects but not quite have less possibility for complications.
or "Who do you think you are?"
A far more pervasive aspect of language design and not one to get into here but the choices inherent in this decision impact many aspects of OOP as mentioned earlier.
Just aspects of the polymorphic late binding can depend on:
The more dynamic a language gets the more complex these decisions tend to become but conversely the more input the language user, rather than the language designer has in the decision. Giving examples here would be some what foolhardy since statically typed languages may be modified to include dynamic aspects (like c# 4.0).