Fraus
Fraus

Reputation: 63

(Beginner Java) Downcasting/Upcasting/Interface

I am studying for an exam and I got stuck on the following question.

Will the following compile? If so, will it run? What is the output?

e) IX i = new C(); A a = (A) i; a.doIt(1.0);

// --- Interfaces and classes
interface IX {void doIt(double d);}

class A implements IX {
public void doIt(double d){out.println("doIt A");}}

class B extends A {public void doIt(int i){out.println("doIt B");}
}

class C extends A{public void doIt(double d){out.println("doIt C");}
}

class D {public void doIt(double d){out.println("doIt D");}
}

So the way I am understanding this after some googling is:

When we say IX i = new C(); we are saying: We are creating an object of SOME type (and it has the reference variable i), but whatever type it is, it has to implement the IX interface. And right now that type is C.

Alright, we then say that the reference variable a, which is refering to an object of type A, is refering to the same object as i, but after we cast it to (A).

So when we call a.doit(1.0) the compiler will look at the type that a has, and check if if has a method called doIt, which takes a double as input. So my guess would be that it should print out "doIt A", but I am wrong. It prints out "doIt C". What am I missing? I have really tried to google but I find the whole subject of downcasting/upcasting rather confusing atm.

Upvotes: 0

Views: 700

Answers (2)

gmanrocks
gmanrocks

Reputation: 281

Correct me if I am wrong, but it something is casted such as Bar b = new Bar(); Foo a = Foo(b) where Bar extends Foo. Foo has a method wobble and bar has an overridden method wobble and a new method wibble. Then b cannot run wibble but it can run wobble. It will run Bar's version of wobble. So basically, it just means that you can only run the methods that Foo has; not the methods Bar has. However, the methods Foo has that are overridden by Bar (such as wobble) will be run via the Bar version. The interface is supposed to trip you up. So in a code example:

abstract class Foo{
    public void wobble() {
        //code A
    }
}

class Bar extends Foo{
    //overridden
    public void wobble() {
        //code B
    }

    public void wibble() {
        //some other code C
    }
}

public class Test {
    public static void main(String[] args) {
        Bar b = new Bar();
        b.wobble(); //runs code B
        b.wibble(); //runs code C

        Foo f = (Foo)b;
        f.wobble(); //runs code B
        f.wibble(); //doesn't compile

        Foo foo2 = new Foo(); //trick cannot instantiate abstract class
        foo2.wobble(); //runs code A (if instantiated which it cant be)
        foo2.wibble(); //will not compile because Foo does not have the wibble method
    }

}

Upvotes: 0

Not a JD
Not a JD

Reputation: 1902

IX i = new C();

Create a new instance of C and assign it static type IX - legal, since C is an IX.

A a = (A) i;

Create a reference A and assign it to static type A. Compile-time and run-time safe. We know that A is the parent class of C.

a.doIt(1.0);

Dispatch a method call to object a and invoke the method A::doIt(double).

This method is overridden by the actual (dynamic) type C. So "doIt C" should be printed.

Upvotes: 2

Related Questions