简体   繁体   English

(初学者Java)向下转换/向上转换/接口

[英](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(); 当我们说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. 我们说的是:我们正在创建一个SOME类型的对象(它具有引用变量i ),但是无论它是什么类型,它都必须实现IX接口。 And right now that type is C . 现在,该类型为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) . 好了,然后我们说引用变量a引用a类型A的对象,它引用的对象与i相同,但是将其转换为(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. 因此,当我们调用a.doit(1.0) ,编译器将查看a具有的类型,并检查是否有一个名为doIt的方法,该方法将double作为输入。 So my guess would be that it should print out "doIt A" , but I am wrong. 所以我的猜测是应该打印出"doIt A" ,但是我错了。 It prints out "doIt C" . 它打印出"doIt C" What am I missing? 我想念什么? I have really tried to google but I find the whole subject of downcasting/upcasting rather confusing atm. 我确实尝试过使用Google,但是我发现向下转换/向上转换的整个主题都使atm感到困惑。

IX i = new C();

Create a new instance of C and assign it static type IX - legal, since C is an IX. 创建一个新的C实例,并为其分配静态类型IX-合法,因为C IX。

A a = (A) i;

Create a reference A and assign it to static type A. Compile-time and run-time safe. 创建引用A并将其分配给静态类型A。编译时和运行时安全。 We know that A is the parent class of C. 我们知道A是C的父类。

a.doIt(1.0);

Dispatch a method call to object a and invoke the method A::doIt(double). 调度对对象a的方法调用,然后调用方法A :: doIt(double)。

This method is overridden by the actual (dynamic) type C. So "doIt C" should be printed. 实际(动态)类型C覆盖了此方法。因此应打印“ doIt C”。

Correct me if I am wrong, but it something is casted such as Bar b = new Bar(); 如果我错了,请纠正我,但是会强制转换,例如Bar b = new Bar(); Foo a = Foo(b) where Bar extends Foo. Foo a = Foo(b),其中Bar扩展Foo。 Foo has a method wobble and bar has an overridden method wobble and a new method wibble. Foo有方法摆动,bar有重写方法摆动和新方法摆动。 Then b cannot run wibble but it can run wobble. 然后b不能摆动,但可以摆动。 It will run Bar's version of wobble. 它将运行Bar版本的摆动。 So basically, it just means that you can only run the methods that Foo has; 因此,基本上,这仅意味着您只能运行Foo拥有的方法。 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. 但是,被Bar覆盖的Foo具有的方法(例如摆动)将通过Bar版本运行。 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
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM