Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overloading in Java and multiple dispatch

I have a collection (or list or array list) in which I want to put both String values and double values. I decided to make it a collection of objects and using overloading ond polymorphism, but I did something wrong.

I run a little test:

public class OOP {     void prova(Object o){         System.out.println("object");     }      void prova(Integer i){     System.out.println("integer");     }      void prova(String s){         System.out.println("string");     }      void test(){         Object o = new String("  ");         this.prova(o); // Prints 'object'!!! Why?!?!?     }      public static void main(String[] args) {         OOP oop = new OOP();         oop.test(); // Prints 'object'!!! Why?!?!?     } } 

In the test seems like the argument type is decided at compile time and not at runtime. Why is that?

This question is related to:

Polymorphism vs Overriding vs Overloading
Try to describe polymorphism as easy as you can

EDIT:

Ok the method to be called is decided at compile time. Is there a workaround to avoid using the instanceof operator?

like image 551
Vitaly Olegovitch Avatar asked Mar 18 '12 14:03

Vitaly Olegovitch


People also ask

Is multiple dispatch the same as overloading?

The main difference between multiple dispatch and function overloading (esp. as implemented in C++/other OOP langs.) is that overloaded functions still generally have an implicit receiver of fixed type, which constrains method dispatch to only those variants defined for the receiver.

What is multiple dispatch in Java?

Multiple dispatch or multimethods is a feature of some programming languages in which a function or method can be dynamically dispatched based on the run-time (dynamic) type or, in the more general case, some other attribute of more than one of its arguments.

Does Java support multiple dispatch?

Java doesn't support double dispatch. Note that double dispatch is often confused with method overloading, which is not the same thing. Method overloading chooses the method to invoke based only on compile-time information, like the declaration type of the variable.

Can methods be overloaded multiple times?

Introduction. Method overloading is a salient feature in Object-Oriented Programming (OOP). It lets you declare the same method multiple times with different argument lists.


2 Answers

This post seconds voo's answer, and gives details about/alternatives to late binding.

General JVMs only use single dispatch: the runtime type is only considered for the receiver object; for the method's parameters, the static type is considered. An efficient implementation with optimizations is quite easy using method tables (which are similar to C++'s virtual tables). You can find details e.g. in the HotSpot Wiki.

If you want multiple dispatch for your parameters, take a look at

  • groovy. But to my latest knowledge, that has an outdated, slow multiple dispatch implementation (see e.g. this performance comparison), e.g. without caching.
  • clojure, but that is quite different to Java.
  • MultiJava, which offers multiple dispatch for Java. Additionally, you can use
    • this.resend(...) instead of super(...) to invoke the most-specific overridden method of the enclosing method;
    • value dispatching (code example below).

If you want to stick with Java, you can

  • redesign your application by moving overloaded methods over a finer grained class hierarchy. An example is given in Josh Bloch's Effective Java, Item 41 (Use overloading judiciously);
  • use some design patterns, such as Strategy, Visitor, Observer. These can often solve the same problems as multiple dispatch (i.e. in those situations you have trivial solutions for those patterns using multiple dispatch).

Value dispatching:

class C {   static final int INITIALIZED = 0;   static final int RUNNING = 1;   static final int STOPPED = 2;   void m(int i) {     // the default method   }   void m(int@@INITIALIZED i) {     // handle the case when we're in the initialized `state'   }   void m(int@@RUNNING i) {     // handle the case when we're in the running `state'   }   void m(int@@STOPPED i) {     // handle the case when we're in the stopped `state'   } } 
like image 149
DaveFar Avatar answered Sep 25 '22 08:09

DaveFar


What you want is double or more general multiple dispatch, something that is actually implemented in other languages (common lisp comes to mind)

Presumably the main reason java doesn't have it, is because it comes at a performance penalty because overload resolution has to be done at runtime and not compile time. The usual way around this is the visitor pattern - pretty ugly, but that's how it is.

like image 44
Voo Avatar answered Sep 23 '22 08:09

Voo