Does Java support dispatching for specific implementations based on multiple object types such as Lisp?

Reading myself in Lisp, currently on this page ( http://landoflisp.com ), I found the following expression in the second and last paragraph on the page that appears when you click the CLOS GUILD link:

It is important to note that in order to find out which mixing method is invoked in a given situation, CLOS must take into account both objects passed to this method. It sends a concrete implementation of a method based on the types of several objects. This is a feature that is not available in traditional object-oriented languages ​​such as Java or C ++.

Here is an example of Lisp -code:

(defclass color () ()) (defclass red (color) ()) (defclass blue (color) ()) (defclass yellow (color) ()) (defmethod mix ((c1 color) (c2 color)) "I don't know what color that makes") (defmethod mix ((c1 blue) (c2 yellow)) "you made green!") (defmethod mix ((c1 yellow) (c2 red)) "you made orange!") 

No, I think the last sentence is wrong. I really can do just that with the following Java code:

 public class Main { public static void main(String[] args) { mix(new Red(), new Blue()); mix(new Yellow(), new Red()); } public static void mix(Color c1, Color c2) { System.out.println("I don't know what color that makes"); } public static void mix(Blue c1, Yellow c2) { System.out.println("you made green!"); } public static void mix(Yellow c1, Red c2) { System.out.println("you made orange!"); } } class Color {} class Red extends Color {} class Blue extends Color {} class Yellow extends Color {} 

which gives me the same result when I run it:

 I don't know what color that makes you made orange! 

So my question is: is this sentence on this page really wrong and possible in Java / C ++? If so, maybe this was not possible in an older version of Java? (Although I doubt very much that since the book is only 5 years old) If not, what did I forget to consider in my example?

+7
java class lisp multiple-dispatch clos
source share
5 answers

If you change your example to:

 public static void main(String[] args) { Color red = new Red(); Color blue = new Blue(); Color yellow = new Yellow(); mix(red, blue); mix(yellow, red); } 

then you get

 I don't know what color that makes I don't know what color that makes 

Java uses compile-time types to figure out what method overload to invoke, where Lisp sends to run-time types. Java should use the Visitor pattern to send twice (calling another implementation based on both the type of the object called by the method and the type of the argument passed).

+9
source share

Both C ++ and Java can overload methods with several arguments, but this is done statically and is intended only for methods (which for Java are second-class citizens under classes and objects). It does not solve the problem of expression as such: you cannot introduce a new class with a new set of supported argument combinations and work with existing ones.

You can use the reflection engine supported by the JVM and write a class that "registers" methods with its arguments, and store the send data in the repository for this class. Reflection, which helps to infer argument types, is not a quick way to submit to the JVM, but is probably necessary to implement common functions.

+4
source share

The actual way to run OO in Java would be something like this:

 class Color { public static void main(String[] args){ Color red = new Red(); Color blue = new Blue(); Color yellow = new Yellow(); red.printMix(blue); // prints "I don't know what color that makes" red.printMix(yellow); // prints "you made orange!" blue.printMix(yellow); // prints "you made green!" // but these should work as well yellow.printMix(red); // prints "you made orange!" yellow.printMix(blue); // prints "you made green!" } public void printMix(Color c) { System.out.println(mix(c)); } public String mix(Color c){ return "I don't know what color that makes"; } } class Red extends Color { @Override public String mix(Color c){ if( c instanceof Yellow ) return "you made orange!"; return super.mix(c); } } class Blue extends Color { @Override public String mix(Color c){ if( c instanceof Yellow ) return "you made green!"; return super.mix(c); } } class Yellow extends Color { @Override public String mix(Color c){ if( c instanceof Red ) return "you made orange!"; if( c instanceof Blue ) return "you made green!"; return super.mix(c); } } 

Now, if you imagine that Yellow is made by you, and the rest is done by someone else. In CLOS, you can provide (defmethod mix ((c2 red) (c1 yellow)) as part of your implementation of Yellow , but how can you overload public void mix(Color c) in class Blue to return "you made an orange!". Without his changes?

+2
source share

You will get the best image from the example below:

  class PrettyPrint{ public void Print(Customer aCustomer){} public void Print(User aUser){} public void Print(SuperUser aUser){} } 

This is similar to method overloading. But there is a difference: If you do this (assuming that the β€œFace” is the superclass of the user, user, and superuser):

  PrettyPrint pp = ...; Person p = new Customer(...); pp.Print(p); 

then the C # compiler will complain because it does not know which of the three methods it should call. If C # had multi-methods, this will compile and execute as expected, i.e. The first "Seal" will be called up. This is due to the fact that with the help of multimethods dynamic (run-time) types of all arguments (and not just the first ones) are considered at runtime when choosing a call method.

The multimethod call uses the base type for the arguments, but it still finds the appropriate implementations for the derived types.

I think you should read the following link to get a better picture:

http://c2.com/cgi/wiki?MultiMethods

+2
source share

The difference is that in Java you would use the usual class methods (in the class file) to send one argument and you would use a helper class (in your own file) for sending many arguments, as in your example, And it is unified in CLOS , you use one form for everything that splits into files, as it suits you.

+1
source share

All Articles