Zahra19977
Zahra19977

Reputation: 355

Why can't overriding be done at compile time but overloading can?

I know that overloading is done at compile time because number and type of arguments are specified and compiler knows which one method in object was called.

But in overriding why doesn't the compiler see whether a subclass method exist in superclass or not?

If the compiler do not know about classes at the compile time then how does it recognize overloading?

thanks!

Upvotes: 5

Views: 1375

Answers (2)

JB Nizet
JB Nizet

Reputation: 691715

Put yourself in the shoes of the compiler. Imagine you must compile the following method:

public void foo(List<String> list) {
    System.put.println(list.size());
}

How could you possibly know what the concrete type of list is, and thus which concrete implementation of the size() method to call? Is it an ArrayList? A LinkedList? A CopyOnWriteArrayList? You can't know.

If you're not convinced yet, the caller of the method could do something like

if (Math.random() > 0.5) {
    foo(new ArrayList<>());
}
else {
    foo(new LinkedList<>());
}

There is no way to know at compile-time what the concrete type of the list is. You can only know at runtime. So which of the size() method is being called can only be decided at runtime.

Upvotes: 13

Sweeper
Sweeper

Reputation: 271150

Overriding is checked at compile time!

Look at this:

class Base {
    public void myMethod() {}
}

class Derived extends Base {
    @Override // error!
    public void myMethod2() {}
}

The compiler checks whether myMethod2 is in the base class, which it isn't, so the compiler gives an error.

However, deciding which version of an overridden method to call is determined at runtime. This is because to determine which method to call, the runtime type of the object must be known. The compiler cannot know the runtime type of a variable unless it runs your code, at which point it's not "compile"-time anymore...

Look at this:

class Base {
    public void myMethod() {}
}

class Derived extends Base {
    @Override
    public void myMethod() {}
}

// ...

Base obj;
if (Math.random() > 0.5) {
    obj = new Derived();
} else {
   obj = new Base();
}
obj.myMethod();

Proof by contradiction:

If the version of the method to call is decided at compile time, then the myMethod() call here will always call the same version of the method at runtime, no matter how many times you run the code. But from the if statement, we can see that the method to call changes depending on a condition. But this condition varies between different runs of the code. This creates a contradiction, so the version to call must be determined at runtime. QED :).

Upvotes: 4

Related Questions