是添加到ArrayList时的对象?

时间:2013-10-19 16:38:16

标签: java polymorphism

如果我创建了一个界面:wood,它由许多对象实现,例如oakpine

当我创建时:

Pine tree = new Pine();
Oak trunk = new Oak();

ArrayList<wood> woods = ArrayList<wood>();

woods.add(tree);
woods.add(trunk);

并因此使用它:

for(wood tree: woods){
    if(tree.gettype() == PINE)
         tree.getbranch();
    else if(tree.gettype() == OAK)
         tree.gettrunk();
}

树对象是否使用Oak或Pine对象中的方法?

我认为,根据测试,它会使用相应的对象,但我只是想确定。

5 个答案:

答案 0 :(得分:3)

无论何时将某些内容向上转换为其接口类型,您都只能使用该接口定义的方法。

也就是说,您不能使用OakPine定义的任何更专业的方法。您只能使用wood定义的任何内容 因此,如果要使用OakPine定义的方法,则需要将其对象强制转换为适当的类类型。

此:

for(wood tree: woods){
    if(tree.gettype() == PINE)
         tree.getbranch();
    else if(tree.gettype() == OAK)
         tree.gettrunk();
}  

应替换为:

for(wood tree : woods){
    if(wood.getClass().getName().equals("Pine")){
        // chop that tree ! destroy nature !
    }else if(wood.getClass().getName().equals("Oak")){
        // more deforestation !
    }
}

答案 1 :(得分:1)

  

树对象是否使用Oak或Pine对象中的方法?

是。例如,如果在getbranchOak中覆盖Pine,则会调用正在迭代的对象上的版本,而不是wood版本。因此,当您查看Oak时,会调用Oak的版本;当您查看Pine时,会调用Pine的版本。这称为dynamic binding,它是Java唯一的绑定类型。 (某些语言,如C ++,具有动态和静态绑定,具体取决于您声明方法的方式;在Java中,您最接近的是final关键字,这会阻止您完全覆盖该方法[因此允许在相关的编译器中进行静态绑定,例如HotSpot Just-In-Time编译器可以进行的优化。)


附注:

  1. Java中压倒性的惯例是类名大写。更重要的是一致性。因此,如果您有OakPine个类,则其基类应为Wood,而不是wood

  2. 同样,camelCase用于方法(因此,getBranch,而不是getbranch)。

  3. 同样,这是惯例,您可以选择忽略,但在与其他人沟通时(例如,在SO!中),遵循约定是有用的。

答案 2 :(得分:0)

该列表只能包含继承Wood的对象。

当您只是明确地遍历此列表时,只有Wood方法可用。 但是,将使用在Wood中定义的在子类中重写的任何方法(如果您创建Wood作为具有这些方法的实现的抽象类,那么它将回退到如果您有一个不会覆盖它的子类。)

答案 3 :(得分:0)

在你的情况下:

Pine tree = new Pine();
Oak trunk = new Oak();

你甚至不需要在对象上检查类型调用方法,因为对象和引用都是相同的类型。松树或橡树。

如果您使用的是RTP,则需要检查类型。

那就是你创建像wood tree = new Pine()这样的对象。

答案 4 :(得分:0)

请记住引用类型和对象类型之间的区别。

当你说

Pine pine = new Pine();
ArrayList<Wood> woods = ArrayList<Wood>();
woods.add(pine);

没有演员表演,也没有必要。 Pine的类型为Wood,这是List的{​​{1}}。但是当您遍历列表时,请记住引用的类型为Wood,但对象的类型为Wood等。所以当您致电Pine,从wood.getBranch() API /接口/透视图中查看Pine(例如)。

但是,对象本身是WoodPine等等,因此将调用Oak调用这些特定对象的。这是多态性。我可以从广泛的超类引用中获取无限种类对象的特定行为。因此,随着应用程序的发展,我可以添加更多getBranch()个,而且我的代码不需要更改。

除此之外,请记住,如果您正在基于类执行大量条件逻辑,那么您完全错过了面向对象语言的好处。只需坚持C.要了解原因,请想象为WoodSequoia等添加类。你真的想为所有拥有它们的方法添加更多条件吗?这周末工作很多。