Overloading in Java and Multiple Dispatch

Overloading in Java and multiple dispatch

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'
}
}

Does java support multiple dispatch? If not how is the below code working?

First some terminology

Overloading is the ability to create multiple methods of the
same name with different implementations.

In Java, this is performed based on the compile-time type of the arguments, : the method with the matching signature is used, independently of the argument's value.

Overriding allows a subclass or child class to provide a
specific implementation of a method that is already provided by one of
its superclasses or parent classes.

In Java, this is performed by determining the method to be called depending on the run-time (dynamic) type of the object referred to. This is Java's way to implement single dispatch and it is not be confused with overloading.

Multiple dispatch means that 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 ?

In Java, there's no direct support for multiple dispatch.

However you can emulate multiple dispatch by using several layers of single dispatch combined with overloading.

How is this code working ?

Note that this code to work first requires that you provide an implementation of calculateInterest() for LoanAccount and SavingAccount, even if it will not be used in the rest of your POC.

In your class InterestCalculation , you have three distinct overloads of the method getInterestRate(). They each have a distinct signature (e.g. argument type). So main() will invoke the right method depending on the declared type of the argument (which is deduced from the constructor).

You could optimize your use of single dispatch and make InterestCalculation much more general (e.g. you could then add many more implementations of Account without having to change it) :

public interface Account 
{
public void calculateInterest();
public double getInterest();
public String getType();
}
...
public class InterestCalculation
{
public void getInterestRate(Account objAccount)
{
System.out.print ("Interest Rate for "+objAccount.getType()+" is ");
System.out.print (objAccount.getInterest());
System.out.println (" %");
}
}

Online demo

What is the difference between multiple dispatch and method overloading?

Method overloading is resolved at compile time.

Multiple dispatch is resolved at runtime.

When using double dispatch the called method depends on the actual type of receiver and arguments. Method overloading however, only allows the called method to depend on the declared type of the parameters. Why? Java binds method calls at compile time with their full signature (early binding). The full signature includes all parameter types, hence when the actual type of an argument differs at runtime (polymoprhism), overloading does not work as you might expect!

void add(Foo o) { ... }
void add(Bar o) { ... }
void client() {
Foo o = new Bar();
add(o); // calls add(Foo) not add(Bar)!
}

using multiple dispatch however

void add(Foo o) { o.dispatch(this); }
void add(Bar o) { o.dispatch(this); }
void client() {
Foo o = new Bar();
add(o); // calls #dispatch as defined in Bar!
}

Things might slightly differ in Scala, though the general distinction should be the same as presented here in all programming languages.

Java method overloading + double dispatch

The JLS states in §8.4.9 Overloading:

  1. When a method is invoked (§15.12), the number of actual arguments (and any explicit type arguments) and the compile-time types of the arguments are used, at compile time, to determine the signature of the method that will be invoked (§15.12.2).
  2. If the method that is to be invoked is an instance method, the actual method to be invoked will be determined at run time, using dynamic method lookup (§15.12.4).

So in your case:

  1. The method argument (this) is of compile-time type Parent, and so the method print(Parent) is invoked.
  2. If the Worker class was subclassed and the subclass would override that method, and the worker instance was of that subclass, then the overridden method would be invoked.

Double dispatch does not exist in Java. You have to simulate it, e.g. by using the Visitor Pattern. In this pattern, basically, each subclass implements an accept method and calls the visitor with this as argument, and this has as compile-time type that subclass, so the desired method overloading is used.

Dynamic dispatch (runtime-polymorphism) with overloaded methods without using instanceof

Since each sub-class already has to know about the other sub-classes (for example, Arc must be aware of the Line class in order to implement Arc and Line intersection), there is nothing wrong with using instanceof.

In each sub-class you can override the base class's public Point[] intersection(Curve c) method and dispatch the implementation to one of the overloaded methods.

For example:

public class Arc extends Curve {    
@Override
public Point[] intersection(Curve c) {
if (c instanceof Line)
return instersection ((Line) c);
else if (c instanceof Arc)
return intersection ((Arc) c);
else
return an empty array or null, or throw some exception
}

public Point[] intersection(Line l) {
// return intersection Point(s) of this and l
}

public Point[] intersection(Arc a) {
// returns intersection Point(s)
}
}

This way you don't have to change anything in your public static boolean intersect(ArrayList<Curve> list1, ArrayList<Curve> list2) method.

Work around Java's static method dispatching without Double Dispatch/Visitor patterns

Of course you could always use reflection to find the most specific version of the method that applies, but that could get hairy real quick.

But if those two calls result in entirely different behaviour, then Foo is either designed to be used in a visitor pattern (i.e. with double dispatch) or it is broken.

What's the difference between Polymorphism and Multiple Dispatch?

Polymorphism is the facility that allows a language/program to make decisions during runtime on which method to invoke based on the types of the parameters sent to that method.

The number of parameters used by the language/runtime determines the 'type' of polymorphism supported by a language.

Single dispatch is a type of polymorphism where only one parameter is used (the receiver of the message - this, or self) to determine the call.

Multiple dispatch is a type of polymorphism where in multiple parameters are used in determining which method to call. In this case, the reciever as well as the types of the method parameters are used to tell which method to invoke.

So you can say that polymorphism is the general term and multiple and single dispatch are specific types of polymorphism.

Addendum: Overloading happens during compile time. It uses the type information available during compilation to determine which type of method to call. Single/multiple dispatch happens during runtime.

Sample code:

using NUnit.Framework;

namespace SanityCheck.UnitTests.StackOverflow
{
[TestFixture]
public class DispatchTypes
{
[Test]
public void Polymorphism()
{
Baz baz = new Baz();
Foo foo = new Foo();

// overloading - parameter type is known during compile time
Assert.AreEqual("zap object", baz.Zap("hello"));
Assert.AreEqual("zap foo", baz.Zap(foo));

// virtual call - single dispatch. Baz is used.
Zapper zapper = baz;
Assert.AreEqual("zap object", zapper.Zap("hello"));
Assert.AreEqual("zap foo", zapper.Zap(foo));

// C# has doesn't support multiple dispatch so it doesn't
// know that oFoo is actually of type Foo.
//
// In languages with multiple dispatch, the type of oFoo will
// also be used in runtime so Baz.Zap(Foo) will be called
// instead of Baz.Zap(object)
object oFoo = foo;
Assert.AreEqual("zap object", zapper.Zap(oFoo));
}

public class Zapper
{
public virtual string Zap(object o) { return "generic zapper" ; }
public virtual string Zap(Foo f) { return "generic zapper"; }
}

public class Baz : Zapper
{
public override string Zap(object o) { return "zap object"; }
public override string Zap(Foo f) { return "zap foo"; }
}

public class Foo { }
}
}

Create an object with a String and method overloading

This is not just a problem of dealing with primitive types.

Which method to call is decided in compile time, that is, if you want to be able to call different methods depending on the type of the arguments, you'll need several calls (i.e. you need the if-construct).

In other words, it wouldn't work even if doStuff2 took Integer and Double as arguments (your code is basically as good as it gets).

(In fancy words, this is due to the fact that Java has single dispatch. To emulate multiple dispatch you either need to use conditional statements or a visitor pattern.)

Multiple dispatches on an a single overloaded operator in S3 (in R)

You could check inside the function :

'*.Struct'<-function(x,y){
if(inherits(x,'Struct') && inherits(y,'Struct'))
"Struct*Struct"
else if(inherits(y,'Struct'))
"N*Struct"
else
"Struct*N"
}
# N.B.: you don't need to redefine `*`,`*2.Struct` etc

e.g. :

struct1=structure(5,class='Struct')
struct2=structure(3,class='Struct')

struct1*struct2
# [1] "Struct*Struct"
struct1*2
# [1] "Struct*N"
3*struct2
# [1] "N*Struct"

As stated here dispatching works on both arguments with the following rule :

If a method is found for just one argument or the same method is found
for both, it is used. If different methods are found, there is a
warning about ‘incompatible methods’: in that case or if no method is
found for either argument the internal method is used.

So, for example since there's also a *.difftime method define, these cases will give odd results with warnings :

difftimeObj <- Sys.time()-Sys.time()

struct1*difftimeObj
# [1] 0
# attr(,"units")
# [1] "secs"
# attr(,"class")
# [1] "Struct"
# Warning message:
# Incompatible methods ("*.Struct", "*.difftime") for "*"

difftimeObj*struct2
# Time difference of 0 secs
# Warning message:
# Incompatible methods ("*.difftime", "*.Struct") for "*"

while these instead work :

struct1*unclass(difftimeObj)
# [1] "Struct*N"
unclass(difftimeObj)*struct2
# [1] "N*Struct"

# skipping dispatching
`*.Struct`(struct1, difftimeObj)
# [1] "Struct*N"
`*.Struct`(difftimeObj, struct2)
# [1] "N*Struct"


Related Topics



Leave a reply



Submit