Comparison of various OO languages relatively to their late-binding semantics

by Antoine Beugnard

Abstract.
We observe the various interpretations of overriding and overloading in object oriented languages. With the description of an intend, represented as the following UML diagram, we have "naively" implemented in 15 different languages the same piece of code... and obtenained 11 different results.

UML class diagram of the experiement

The question is: How will this model behave?

newA new language signature with Perfect.

(hot) New tables for .NET language interoperability ! Tables A, B and C.
Not so simple !

hot Java changed its semantics from 1.3 to 1.4!!! Signature slot (6,2) changed adopting the Visual Basic signature!

You'll find source of experiment for each language. You are invited to re-do experiments with you own context and compilers. In our experience (for Java and Scala), the semantics of language may evolve... and we are interested in taking track of that. Thanks for you help.

Outline

1. The test procedure for a single language...

2. The test procedures for languages interaction...

Results are presented in a table 3x6 for all possible calls. Note that only single late-binding is evaluated, and not multiple late-binding, even if some languages enable it (CLOS, Dylan). Results reading help is here.
3. Four proposals for a unified late-binding semantics : A pragmatic, a reasonable (and a non-incremental variant), a strict one and the (new)dont-surprise-the-programner semantics.

4. Tested languages : Ada95, C++, C#, CLOS, Dylan, Eiffel, Java (1.3 and 1.4 are different), nice, OCaml, Perfect, Python, Scala (1.1 and 2.0 are different), Ruby, SmalltalkStrongtalk, Visual Basic (To be tested...Beta, and others if you want to contribute). and tested language interaction using 2 .NET languages: VisualBasic/C++, VisualBasic/C#, C++/VisualBasic, C++/C#, C#/VisualBasic, C#/C++

5. Comparisons for receivers Up u = new Up, Down d = new Down, Up ud = new Down

6. Tested language interaction using 3 .NET languages: C# client, VisualBasic client, C++ client.
 -- Tested language interaction using CORBA (to be done)

7. Code transformation in order to simulate the reasonable semantics in Eiffel, Java and C++

8. Conclusion and future work (PhD, thèses) and discussion...

Some related works : Overloading and Inheritance


1. The programme for testing a single language late-binding semantics

5 classes are needed. 3 for parameters types (all code in a pseudo language):

class Top end class
class Middle extends Top end class
class Bottom extends Middle end class

2 for the method redefinition tests. cv for covariant redefinition, inv for invariant redifinition and ctv for contravariant one:

class Up
method cv(Top t) print "Up" end method
method inv(Middle) print "Up" end method
method ctv(Bottom b) print "Up" end method
end class

class Down extends Up
method cv(Middle m) print "Down" end method
method inv(Middle) print "Down" end method
method ctv(Midle m) print "Down" end method
end class

A main program instantiates objets and makes all possible calls:
procedure main()
Up u = new Up
Down d = new Down
Up ud = new Down
 
-- first column -- second column -- third column 
u.cv(new Top) d.cv(new Top) ud.cv(new Top)
u.cv(new Middle) d.cv(new Middle) ud.cv(new Middle)
u.cv(new Bottom) d.cv(new Bottom) ud.cv(new Bottom)
u.inv(new Top) d.inv(new Top) ud.inv(new Top)
u.inv(new Middle) d.inv(new Middle) ud.inv(new Middle)
u.inv(new Bottom) d.inv(new Bottom) ud.inv(new Bottom)
u.ctv(new Top) d.ctv(new Top) ud.ctv(new Top)
u.ctv(new Middle) d.ctv(new Middle) ud.ctv(new Middle)
u.ctv(new Bottom) d.ctv(new Bottom) ud.ctv(new Bottom)

end procedure

So what is behavior of this code ?

For sake of brevity we have suppressed the simple invariant case - inv(Middle) defined in Up and Down - since all languages behave identically. However, some tables include inv lines for compaison purpose. Results are presented in a table 3x6 for all possible calls. Note that only single late-binding is evaluated, and not multiple late-binding, even if some languages enable it (CLOS, Dylan). Results reading help is here.


2. The programme for testing languages interaction late-binding semantics

5 classes are needed. 3 for parameters types (all code in a FIRST pseudo language):

class Top end class
class Middle extends Top end class
class Bottom extends Middle end class

1 for the methods definition (in the FIRST pseudo language):

class Up
method cv(Top t) print "Up" end method
method inv(Middle) print "Up" end method
method ctv(Bottom b) print "Up" end method
end class

1 for the method redefinition tests. cv for covariant and ctv for contravariant redifinition (in the SECOND pseudo language):

import Up, Top, Middle, Bottom

class Down extends Up
method cv(Middle m) print "Down" end method
method inv(Middle) print "Down" end method
method ctv(Midle m) print "Down" end method
end class

A main program (in a THIRD pseudo language) instantiates objets and makes all possible calls (in the FIRST pseudo language or SECOND pseudo language):
procedure main()
Up u = new Up
Down d = new Down
Up ud = new Down
 
-- first column -- second column -- third column 
u.cv(new Top) d.cv(new Top) ud.cv(new Top)
u.cv(new Middle) d.cv(new Middle) ud.cv(new Middle)
u.cv(new Bottom) d.cv(new Bottom) ud.cv(new Bottom)
u.ctv(new Top) d.ctv(new Top) ud.ctv(new Top)
u.ctv(new Middle) d.ctv(new Middle) ud.ctv(new Middle)
u.ctv(new Bottom) d.ctv(new Bottom) ud.ctv(new Bottom)

end procedure


3. Possible Unified Semantics

We have included inv(Middle) calls in order to show the discontinuity that appears in the thrird column when an invariant semantics is chosen (C++, C#, Java,...)
Here are rationale of these semantics...(comming soon)
 
Table 1 : Reasonable semantics

u
d
ud
cv(Top) Up Up Up
cv(Middle) Up Down Down
cv(Bottom) Up Down Down
ctv(Top) Compilation error Compilation error Compilation error
ctv(Middle) Compilation error Down Compilation error
ctv(Bottom) Up Down Down
inv(Top) Compilation error Compilation error Compilation error
inv(Middle) Up Down Down
inv(Bottom) Up Down Down
Note : Almost never implemented ! The most specialized method selected, covariant and contravariant redefinition possible. Slot (5,3) for incremental compilation. The third columns is continuous...
 
Table 1 bis : Non incremental Reasonable semantics

u
d
ud
cv(Top) Up Up Up
cv(Middle) Up Down Down
cv(Bottom) Up Down Down
ctv(Top) Compilation error Compilation error Compilation error
ctv(Middle) Compilation error Down Down
ctv(Bottom) Up Down Down
inv(Top) Compilation error Compilation error Compilation error
inv(Middle) Up Down Down
inv(Bottom) Up Down Down
Note : Almost implemented by CLOS and Dylan. The most specialized method selected, covariant and contravariant redefinition possible. Slot (5,3) prevents incremental compilation. The third columns is still continuous...
 
Table 2 : Pragmatic semantics

u
d
ud
cv(Top) Up Up Up
cv(Middle) Up Down Up
cv(Bottom) Up Down Up
ctv(Top) Compilation error Compilation error Compilation error
ctv(Middle) Compilation error Down Compilation error
ctv(Bottom) Up Down Up
inv(Top) Compilation error Compilation error Compilation error
inv(Middle) Up Down Down
inv(Bottom) Up Down Down
Note : Invariant semantics. Covariant and contravariant forbiden. This is C# choice is close to Java and C++ one. The third column HAS A DISCONTINUITY
 
Table 2bis : Strict semantics

u
d
ud
cv(Top) Up Down Down
cv(Middle) Up Down Down
cv(Bottom) Up Down Down
ctv(Top) Compilation error Compilation error Compilation error
ctv(Middle) Compilation error Compilation error Compilation error
ctv(Bottom) Up Down Down
inv(Top) Compilation error Compilation error Compilation error
inv(Middle) Up Down Down
inv(Bottom) Up Down Down
Note : Redefinitions with different type of argument is forbiden. Down::cv(Middle) and ctv(Middle) cannot be defined but Down::cv(Top) and Down::ctv(Bottom) can.
Slots (1,2) and (1,3) are yellow since cv cannot be specialized in cv(Middle) but do not generate runtime errors since cv(Top) exists in Down. Covariant redefinitions are forbiden as contravariant ones, the latter generate compilation errors: blue slot(5,3).

Table 2ter : Dont-surprise-the-programner semantics

u
d
ud
cv(Top) Up Up Up
cv(Middle) Up Down Down
cv(Bottom) Up Down Down
ctv(Top) Compilation error Compilation error Compilation error
ctv(Middle) Compilation error Compilation error Compilation error
ctv(Bottom) Up Up Up
inv(Top) Compilation error Compilation error Compilation error
inv(Middle) Up Down Down
inv(Bottom) Up Down Down
Note : Suggested bu Howard Lovatt. Columns 2, d, and 3, ud, should be the same since the object in question is a d. Row 5, ctv(m), column 3, ud, should be E, since most programmers wouldn't expect to have to re-compile super classes when deriving. Contravariance is forbiden.


My favorites are :
    winner : Table 1; allows consitent covariant and contravariant redefinitions and incremental compilers. Homogeneous behavior.
    outsider : Table 2bis : Simple. Homegenous behavior but misses advantages of Table 1.
    outsider : Table 2 : Close to popular OO languages. Simple incremental modification to compilers of Java and C++ to apply it. But heterogeneous...


Color interpretation


4. Languages semantics

Table 3 : Ada 95

u
d
ud
cv(Top) Up Up Up
cv(Middle) Compilation error Down Compilation error
cv(Bottom) Compilation error Compilation error Compilation error
ctv(Top) Compilation error Compilation error Compilation error
ctv(Middle) Compilation error Down Compilation error
ctv(Bottom) Up Up Up

Note : A lot of over-constraints that may be explain by the phrase (Ada95 Ref. Manual) "No complicated method lookup is involved" 3.9(1e) but the constraints seem be the result of a non-use of argument type conformance. See code and result.
 
Table 4 : C++, Scala 1.1

u
d
ud
cv(Top) Up Compilation error Up
cv(Middle) Up Down Up
cv(Bottom) Up Down Up
ctv(Top) Compilation error Compilation error Compilation error
ctv(Middle) Compilation error Down Compilation error
ctv(Bottom) Up Down Up

Note : Invariant semantics (ud shows that no covariant or contravariant is taken into account); slot (1,2) is over-constrained. See code and results for C++. See code and results for Scala.
 
Table 5 : C#

u
d
ud
cv(Top) Up Up Up
cv(Middle) Up Down Up
cv(Bottom) Up Down Up
ctv(Top) Compilation error Compilation error Compilation error
ctv(Middle) Compilation error Down Compilation error
ctv(Bottom) Up Down Up

Note : Invariant semantics (ud shows that no covariant or contravariant is taken into account). This is the pragmatic semantics. See code and results.
 
Table 6 : CLOS and Dylan

u
d
ud
cv(Top) Up Up Up
cv(Middle) Up Down Down
cv(Bottom) Up Down Down
ctv(Top) Runtime error Runtime error Runtime error
ctv(Middle) Runtime error Down Down
ctv(Bottom) Up Down Down

Note : Close to reasonable semantics, accepts typing runtime risks. For CLOS, see code and results. For Dylan, see code and results.
 
Table 7 : Eiffel

u
d
ud
cv(Top) Up Compilation error Down
cv(Middle) Up Down Down
cv(Bottom) Up Down Down
ctv(Top) Compilation error Compilation error Compilation error
ctv(Middle) Compilation error Compilation error Compilation error
ctv(Bottom) Up Up Up

Note : Covariant semantics, contravariance forbiden (lines 4, 5 and 6); slot (1,3) is runtime error prone. See code and results.
A recent proposal from B. meyer to remove the slot (1,3) problem is discussed here : CATcalls.
A possible code transformation to make Eiffel match the "reasonable sematics".
 
Table 8 : Java before 1.3 and Scala 2.0 (and probably before)

u
d
ud
cv(Top) Up Up Up
cv(Middle) Up Down Up
cv(Bottom) Up Down Up
ctv(Top) Compilation error Compilation error Compilation error
ctv(Middle) Compilation error Down Compilation error
ctv(Bottom) Up Compilation error Up

Note : Invariant semantics (ud shows that no covariant or contravariant is taken into account); slot (6,2) is over-constrained. See code and results (java 1.3). See code and results (scala 2.0).

Table 8 bis : Java after 1.4

u
d
ud
cv(Top) Up Up Up
cv(Middle) Up Down Up
cv(Bottom) Up Down Up
ctv(Top) Compilation error Compilation error Compilation error
ctv(Middle) Compilation error Down Compilation error
ctv(Bottom) Up Up Up
Note : Invariant semantics (ud shows that no covariant or contravariant is taken into account); slot (6,2) could be more specialized (as Visual Basic). See code and results.

 
Table 9 : nice (naive translation)

u
d
ud
cv(Top) Up Up Up
cv(Middle) Up Down Down
cv(Bottom) Up Down Down
ctv(Top) Compilation error Compilation error Compilation error
ctv(Middle) Compilation error Down Compilation error
ctv(Bottom) Up Compilation error Up

Note : This is the result of a naive translation. a ctv(Middle) is specified in Down. Multiple late-binding, but contravariance not allowed. See code and results.
Another translation, more in the spirit of nice, but less naive gives results of table 9bis. See code and result.
 
Table 9bis : nice

u
d
ud
cv(Top) Up Up Up
cv(Middle) Up Down Down
cv(Bottom) Up Down Down
ctv(Top) Compilation error Compilation error Compilation error
ctv(Middle) Compilation error Compilation error Compilation error
ctv(Bottom) Up Down Down

 
Table 10 : OCaml

u
d
ud
cv(Top) Up Down Down
cv(Middle) Up Down Down
cv(Bottom) Up Down Down
ctv(Top) Up Down Down
ctv(Middle) Up Down Down
ctv(Bottom) Up Down Down

Note : In spite of appearances, no runtime errors could occur since OCaml compiler detects type problems when they exist ! See code and results. I know that Top, Middle and Bottom classes are equivalent in OCaml sense. Hence, this test may appear unfair. In a sense its true. But why couldn't a programmer or a designer decide to have many classes with exactly the same interface but with different method implentation? There is some "semantics" in the name!
 
Table 10.5 : Perfect

u
d
ud
cv(Top) Up Error Error
cv(Middle) Up Down Down
cv(Bottom) Up Down Down
ctv(Top) Error Error Error
ctv(Middle) Error Down Down
ctv(Bottom) Up Down Down

I did not make the test myself.The table is extracted from page 10 of the technical repport NUIM-CS-TR-2005-07, Software Specification, Implementation and Execution with Perfect by Gareth Carter and Rosemary Monahan. As far as I know, it is the first time, the "language signature" is used during the design of a language! Not as a decision tool to choose the semantics, but as a kind of test.  
Table 11 : Smalltalk, Python or Ruby

u
d
ud
cv(Top) Up Down Down
cv(Middle) Up Down Down
cv(Bottom) Up Down Down
ctv(Top) Up Down Down
ctv(Middle) Up Down Down
ctv(Bottom) Up Down Down

Note : Smalltalk is not typed, so many runtime errors could occur ! But there is a very good regularity. See Smalltalk code and results.See Python code and results.  See Ruby code and results.
 

Table 12 : Strongtalk


d
ud
cv(Top) Up Up Up
cv(Middle) Up Up Up
cv(Bottom) Up Up Up
ctv(Top) Compilation error Compilation error Compilation error
ctv(Middle) Compilation error Down Compilation error
ctv(Bottom) Up Down Down
Note : Strongtalk is typed and adopts a contravariant redefinition rule. See code and results.

Table 13 : Visual Basic

u
d
ud
cv(Top) Up Up Up
cv(Middle) Up Down Up
cv(Bottom) Up Down Up
ctv(Top) Compilation error Compilation error Compilation error
ctv(Middle) Compilation error Down Compilation error
ctv(Bottom) Up Up Up
Note : Column 2 is strange...as if no contravriant were accepted (as for Eiffel) but for slot (5,2) ! See code and results.


Language interoperability using .NET (2 languages case)

Table 14 : C# to (managed) C#, Visual Basic, C++

u
d
ud
cv(Top) Up Up Up
cv(Middle) Up Down Up
cv(Bottom) Up Down Up
ctv(Top) Compilation error Compilation error Compilation error
ctv(Middle) Compilation error Down Compilation error
ctv(Bottom) Up Down Up
Note : Code see C# Client here and Component C#, VisualBasic, C++ . All results
 
Table 15 : C++ to (managed) C#, Visual Basic, C++

u
d
ud
cv(Top) Up Compilation error Up
cv(Middle) Up Down Up
cv(Bottom) Up Down Up
ctv(Top) Compilation error Compilation error Compilation error
ctv(Middle) Compilation error Down Compilation error
ctv(Bottom) Up Down Up
Note : Code see C++ Client here and Component C#, VisualBasic, C++ . All results
 
Table 16 : Visual Basic to (managed) C#, Visual Basic, C++

u
d
ud
cv(Top) Up Up Up
cv(Middle) Up Down Up
cv(Bottom) Up Down Up
ctv(Top) Compilation error Compilation error Compilation error
ctv(Middle) Compilation error Down Compilation error
ctv(Bottom) Up Up Up
Note : Code see VisualBasic Client here and Component C#, VisualBasic, C++ . All results

The semantics depends on the calling program language.


5. Comparisons for each receivers

Table 17 : Up u = new Up

Ada95 C++ C# CLOS/Dylan Eiffel Java OCaml Python/Smalltalk VisualBasic
cv(Top) Up Up Up Up Up Up Up Up Up
cv(Middle) Compilation error Up Up Up Up Up Up Up Up
cv(Bottom) Compilation error Up Up Up Up Up Up Up Up
ctv(Top) Compilation error Compilation error Compilation error Runtime error Compilation error Compilation error Up Up Compilation error
ctv(Middle) Compilation error Compilation error Compilation error Runtime error Compilation error Compilation error Up Up Compilation error
ctv(Bottom) Up Up Up Up Up Up Up Up Up
Note : functional languages (CLOS, Dylan, OCaml, Smalltalk) accept more risks...The distinction between OCaml and Smalltalk is due to the OCaml compiler that would not have compiled code where the type would have trigger errors (yellow is safe !).
 
Table 18 : Down d = new Down

Ada95 C++ C# CLOS/Dylan Eiffel Java OCaml Python/Smalltalk VisualBasic
cv(Top) Up Compilation error Up Up Compilation error Up Down Down Up
cv(Middle) Down Down Down Down Down Down Down Down Down
cv(Bottom) Compilation error Down Down Down Down Down Down Down Down
ctv(Top) Compilation error Compilation error Compilation error Runtime error Compilation error Compilation error Down Down Compilation error
ctv(Middle) Down Down Down Down Compilation error Down Down Down Down
ctv(Bottom) Up Down Down Down Up Compilation error Down Down Up
Note : Line 1 shows 2 over constraints for C++ and Eiffel. Eiffel refuses contravariance. OCaml and Smalltalk are very regular.
 
Table 19 : Up ud = new Down

Ada95 C++ C# CLOS/Dylan Eiffel Java OCaml Python/Smalltalk VisualBasic
cv(Top) Up Up Up Up Down Up Down Down Up
cv(Middle) Compilation error Up Up Down Down Up Down Down Up
cv(Bottom) Compilation error Up Up Down Down Up Down Down Up
ctv(Top) Compilation error Compilation error Compilation error Runtime error Compilation error Compilation error Down Down Compilation error
ctv(Middle) Compilation error Compilation error Compilation error Down Compilation error Compilation error Down Down Compilation error
ctv(Bottom) Up Up Up Down Up Up Down Down Up
Note : Eiffel is not type error free. Functional languages accept Down on line 5 (potential incremental compilation problems).


6. Language interoperability using .NET (3 languages case)

  1. A first library is compiled from the FIRST language (among CS - C# -, VB - VisualBasic -, and VC - managed C++). It contains Up, Top, Middle and Bottom. (3 dll versions)
  2. A second library is compiled from the SECOND language, using the FIRST languages version. It contains the Down class. (3 * 3 = 9 dll versions)
  3. An executable is built from the THIRD language, using one among the 9 previous librairies. (27 exe versions) [source (100 k)] [source-and-bin (1.7 M)]

C# Client

The 9 first tables for the C# exe. On each line of 3 tables only the second librairy (Down) changes.
Results are regular but for slot (1,2) when Down is programmed in C++. So, for instance, replacing a VB/dll by a C++/dll will require a exe C# recompilation !
Table A is a simplified presentation of these results (where language signature is used as results).

Tables 20 : CS as Client and Up, Top, Middle, Bottom
CSCSCS u d ud CSVBCS u d ud CSVCCS u d ud
cv(T) U/CS U/CS U/CS cv(T) U/CS U/CS U/CS cv(T) U/CS X U/CS
cv(M) U/CS D/CS U/CS cv(M) U/CS D/VB U/CS cv(M) U/CS D/VC U/CS
cv(B) U/CS D/CS U/CS cv(B) U/CS D/VB U/CS cv(B) U/CS D/VC U/CS
ctv(T) X X X ctv(T) X X X ctv(T) X X X
ctv(M) X D/CS X ctv(M) X D/VB X ctv(M) X D/VC X
ctv(B) U/CS D/CS U/CS ctv(B) U/CS D/VB U/CS ctv(B) U/CS D/VC U/CS
Tables 21 : CS as Client and VisualBasic for Up, Top, Middle Bottom
CSCSVB u d ud CSVBVB u d ud CSVCVB u d ud
cv(T) U/VB U/VB U/VB cv(T) U/VB U/VB U/VB cv(T) U/VB X U/VB
cv(M) U/VB D/CS U/VB cv(M) U/VB D/VB U/VB cv(M) U/VB D/VC U/VB
cv(B) U/VB D/CS U/VB cv(B) U/VB D/VB U/VB cv(B) U/VB D/VC U/VB
ctv(T) X X X ctv(T) X X X ctv(T) X X X
ctv(M) X D/CS X ctv(M) X D/VB X ctv(M) X D/VC X
ctv(B) U/VB D/CS U/VB ctv(B) U/VB D/VB U/VB ctv(B) U/VB D/VC U/VB
Tables 22 : CS as Client and C++ for Up, Top, Middle Bottom
CSCSVC u d ud CSVBVC u d ud CSVCVC u d ud
cv(T) U/VC U/VC U/VC cv(T) U/VC U/VC U/VC cv(T) U/VC X U/VC
cv(M) U/VC D/CS U/VC cv(M) U/VC D/VB U/VC cv(M) U/VC D/VC U/VC
cv(B) U/VC D/CS U/VC cv(B) U/VC D/VB U/VC cv(B) U/VC D/VC U/VC
ctv(T) X X X ctv(T) X X X ctv(T) X X X
ctv(M) X D/CS X ctv(M) X D/VB X ctv(M) X D/VC X
ctv(B) U/VC D/CS U/VC ctv(B) U/VC D/VB U/VC ctv(B) U/VC D/VC U/VC

VisualBasic Client

The 9 first tables for the VisualBasic exe. On each line of 3 tables only the second librairy (Down) changes.
Sémantique VB
Results are conform to VB semantics but for slot (1,2) and slot (6,2) when Down is programmed in C++ that triggers a compilation error or find in Down instead of Up respectively.
Table B is a simplified presentation of these results (where language signature is used as results).
 
Tables 23 : VB as Client and CS for Up, Top, Middle Bottom
VBCSCS u d ud VBVBCS u d ud VBVCCS u d ud
cv(T) U/CS U/CS U/CS cv(T) U/CS U/CS U/CS cv(T) U/CS X U/CS
cv(M) U/CS D/CS U/CS cv(M) U/CS D/VB U/CS cv(M) U/CS D/VC U/CS
cv(B) U/CS D/CS U/CS cv(B) U/CS D/VB U/CS cv(B) U/CS D/VC U/CS
ctv(T) X X X ctv(T) X X X ctv(T) X X X
ctv(M) X D/CS X ctv(M) X D/VB X ctv(M) X D/VC X
ctv(B) U/CS U/CS U/CS ctv(B) U/CS U/CS U/CS ctv(B) U/CS D/VC U/CS
Tables 24 : VB as Client and Up, Top, Middle Bottom
VBCSVB u d ud VBVBVB u d ud VBVCVB u d ud
cv(T) U/VB U/VB U/VB cv(T) U/VB U/VB U/VB cv(T) U/VB X U/VB
cv(M) U/VB D/CS U/VB cv(M) U/VB D/VB U/VB cv(M) U/VB D/VC U/VB
cv(B) U/VB D/CS U/VB cv(B) U/VB D/VB U/VB cv(B) U/VB D/VC U/VB
ctv(T) X X X ctv(T) X X X ctv(T) X X X
ctv(M) X D/CS X ctv(M) X D/VB X ctv(M) X D/VC X
ctv(B) U/VB U/VB U/VB ctv(B) U/VB U/VB U/VB ctv(B) U/VB D/VC U/VB
Tables 25 : VB as Client and C++ for Up, Top, Middle Bottom
VBCSVC u d ud VBVBVC u d ud VBVCVC u d ud
cv(T) U/VC U/VC U/VC cv(T) U/VC U/VC U/VC cv(T) U/VC X U/VC
cv(M) U/VC D/CS U/VC cv(M) U/VC D/VB U/VC cv(M) U/VC D/VC U/VC
cv(B) U/VC D/CS U/VC cv(B) U/VC D/VB U/VC cv(B) U/VC D/VC U/VC
ctv(T) X X X ctv(T) X X X ctv(T) X X X
ctv(M) X D/CS X ctv(M) X D/VB X ctv(M) X D/VC X
ctv(B) U/VC U/VC U/VC ctv(B) U/VC D/VB U/VC ctv(B) U/VC D/VC U/VC

C++ Client

The 9 first tables for the C++ exe. On each line of 3 tables only the second librairy (Down) changes.
Results are conform to C++ semantics but for slot (6,2) when Down is programmed in C#!
Table C is a simplified presentation of these results (where language signature is used as results).
 
Tables 26 : VC as Client and CS for Up, Top, Middle Bottom
VCCSCS u d ud VCVBCS u d ud VCVCCS u d ud
cv(T) U/CS X U/CS cv(T) U/CS X U/CS cv(T) U/CS X U/CS
cv(M) U/CS D/CS U/CS cv(M) U/CS D/VB U/CS cv(M) U/CS D/VC U/CS
cv(B) U/CS D/CS U/CS cv(B) U/CS D/VB U/CS cv(B) U/CS D/VC U/CS
ctv(T) X X X ctv(T) X X X ctv(T) X X X
ctv(M) X D/CS X ctv(M) X D/VB X ctv(M) X D/VC X
ctv(B) U/CS U/CS U/CS ctv(B) U/CS U/CS U/CS ctv(B) U/CS U/CS U/CS
Tables 27 : VC as Client and VB for Up, Top, Middle Bottom
VCCSVB u d ud VCVBVB u d ud VCVCVB u d ud
cv(T) U/VB X U/VB cv(T) U/VB X U/VB cv(T) U/VB X U/VB
cv(M) U/VB D/CS U/VB cv(M) U/VB D/VB U/VB cv(M) U/VB D/VC U/VB
cv(B) U/VB D/CS U/VB cv(B) U/VB D/VB U/VB cv(B) U/VB D/VC U/VB
ctv(T) X X X ctv(T) X X X ctv(T) X X X
ctv(M) X D/CS X ctv(M) X D/VB X ctv(M) X D/VC X
ctv(B) U/VB D/CS U/VB ctv(B) U/VB D/VB U/VB ctv(B) U/VB D/VC U/VB
Tables 28 : VC as Client and Up, Top, Middle Bottom
VCCSVC u d ud VCVBVC u d ud VCVCVC u d ud
cv(T) U/VC X U/VC cv(T) U/VC X U/VC cv(T) U/VC X U/VC
cv(M) U/VC D/CS U/VC cv(M) U/VC D/VB U/VC cv(M) U/VC D/VC U/VC
cv(B) U/VC D/CS U/VC cv(B) U/VC D/VB U/VC cv(B) U/VC D/VC U/VC
ctv(T) X X X ctv(T) X X X ctv(T) X X X
ctv(M) X D/CS X ctv(M) X D/VB X ctv(M) X D/VC X
ctv(B) U/VC D/CS U/VC ctv(B) U/VC D/VB U/VC ctv(B) U/VC D/VC U/VC

.NET faces a real problem. Component are not substituable if they are programmed in different languages...


A simplified presentation of the language interaction is shown in Table A, B and C. We use language signatures (when possible) as results.
See C#, Visual Basic, C++ signatures.

In table A, the client is in C#. The framework languages are in the columns. The extension languages (for Down) are in lines. It is a simplification of Table 19, 20 and 21.

Tables A : C# as Client
Extension\Framework C# VB C++
C# C# C# C++
VB C# C# C++
C++ C# C# C++

In table B, the client is in Visual Basic. The framework languages are in the columns. The extension languages (for Down) are in lines. It is a simplification of Table 22, 23 and 24.

Tables B : Visual Basic as Client
Extension\Framework C# VB C++
C# VB
VB
C++
VB VB VB C++
C++ VB C# C++

In table C, the client is in C++. The framework languages are in the columns. The extension languages (for Down) are in lines. It is a simplification of Table 25, 26 and 27.
Note that the first line has a signature which is not one of studied languages (Ada95, C++, C#, CLOS, Dylan, Eiffel, Java, nice, OCaml, Python, Scala, Smalltalk, Visual Basic).

Tables C : C++ as Client
Extension\Framework C# VB C++
C# VB/C++ VB/C++ VB/C++
VB C++ C++ C++
C++ C++ C++ C++

As a temporary conclusion, we can say that the only way to build a component that always answer as the client expect is to write the framework/extension with the following couple : C#/VB, C#/C++ and VB/VB !! (the dark green slots that are always equal to the client language...).

7. Code transformation

In order to simulate the reasonable semantics, it is possible to program the test suite less naively, using explicit casting or type testing...

8. Conclusion

OO programming may seem natural and easy. Once inheritance is understood everything is clear! sure? I hope these experiments and tables ask questions ...
The proposed tables could be considered as a "language signature" from the late-binding semantics. An idea to explore is how language signatures could be used to forecast interactions of different languages...

To become mature OO paradigm needs a unified semantics and not only a unified notation...the UML Action Semantics is one step forward, but still remain confusing on the meaning of the lookup procedure which is, to my opinion, the key point of OO semantics. [Beu02-3] makes somme proposals.

I propose two semantics: a reasonable semantics, that offers the best specialization and good continuity properties (when we consider multiple late-binding) and a pragmatic one, with "lesser good" properties, but closer to many popular languages, and therefore a good candidate. C# implements it and a small and incremental change in the compiliers of C++ and Java could make all these three languages adopting the same late-binding behavior.

(new)(hot)The last conclusion that comes from the observation of tables A, B and C is the following : are components compatible with the object paradigm?

Considering the most recen results, my position is now to restrict OO programming languages to a strict invariance redefinition and overriding forbidance. As for structuring languages it has been useful to limit the use of the GOTO, I consider that for allowing OO language interoperability it is necessary to restrict the use of overriding and overloading.

Future work (I'm looking for funding :-):

  1. The most pertinent (low cost, minimal research) approach to make languages dynamically interoperable seems to adopt the pragmatic semantics and to make C++ accept to compile slot (1,2) and java slot (6,2). This very little semantics shift would lead to a unification af C#, C++ and Java behavior...
  2. Another approach consists in selecting a pivot semantics (pragmatic or reasonable) and to program and model using this common semantics. Then different compilers will generate the target language code corresponding to the unified semantics - with all explicit cast required ! UML/Action Semantics could adopt this strategy.
  3. Accepting diversity, and trying to better undestand late-binding language interaction...using "signature operators"...

Thanks

Special thanks to Olivier Aubert who contibutes for Python and to Martin Monperrus who contributes for Ruby.
And to Roger Rousseau for the Eiffel code transformation used to make Eiffel match the "reasonable semantics".
Thanks to Howard Lovatt for the interesting discussions we have and the suggestions he made.
Thanks  to Tobias Wahl for detecting the Java semantics change from 1.3  to 1.4.

Références

[Beu02-1] Antoine Beugnard, "OO languages Late-binding Signature", accepted at FOOL 9 (The Ninth International Workshop on Foundations of Object-Oriented Languages) , Portland, Oregon, january 19, 2002.
[Beu02-2] Antoine Beugnard, "Une comparaison de langages objet relative au traitement de la redéfinition de méthode et à la liaison dynamique", LMO 2002, Montpellier, 23-25 janvier 2002. (slides pdf)
[Beu02-3] Antoine Beugnard, "Is UML Action Semantics precise enough? Can Software Engineering do without semantics?", submitted to ICSE 2002
[Beu05] Antoine Beugnard, "Peut-on réaliser des composants avec un langage à objets ?", LMO 2005, Berne, 9-11 mars 2005.
[Beu06] Antoine Beugnard, "Method overloading and overriding cause encapsulation flaw", Object-Oriented Programming Languages and Systems, 21st ACM symposium on  Applied Computing (SAC), Dijon, France, Appril 23-27 2006.
[CM05] Gareth Carter and Rosemary Monahan, "Software Specification, Implementation and Execution with Perfect", Technical Report, National University of Ireland, Maynooth Maynooth, Co Kildare, Ireland, Department of computer science, technical report series, NUIM-CS-TR-2005-07, 2005

updated the 26 may 2011
by Antoine Beugnard, ENST-Bretagne