0

如果我创建一个接口: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 对象中的方法?

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

4

5 回答 5

3

每当您将某些内容向上转换为它们的接口类型时,您只能使用由该接口定义的方法。

也就是说,您不能使用由Oak和定义的任何更专业的方法Pine。您只能使用任何wood定义。
因此,如果您想使用由Oakand定义的方法Pine,您需要将它们的对象向下转换为相应的类类型。

这个:

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 !
    }
}
于 2013-10-19T16:41:36.577 回答
1

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

是的。例如,如果在orgetbranch中被覆盖,则调用被迭代对象的版本,而不是版本。因此,当您查看,的版本时;当您查看 a 时,会调用,的版本。这称为动态绑定,它是 Java 唯一的绑定类型。(某些语言,如 C++,根据您声明方法的方式同时具有动态和静态绑定;在 Java 中,最接近的是关键字,它可以防止您完全覆盖方法 [因此允许在相关的编译器,例如 HotSpot Just-In-Time 编译器可以做的优化]。)OakPinewoodOakOakPinePinefinal


旁注:

  1. Java 中压倒性的约定是类名大写。更重要的是一致性。所以如果你有OakPine类,它们的基类应该是Wood,而不是wood

  2. 类似地,camelCase 用于方法(so, getBranch, not getbranch)。

同样,这是约定,您可以选择忽略它,但是在与他人交流时(例如,在 SO!),遵循约定很有用。

于 2013-10-19T16:40:28.823 回答
0

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

当你说

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

没有演员表发生,也没有必要。Pine是 类型Wood,这是Lists的一个Wood。但是当您遍历列表时,请记住引用是 type Wood,但对象是 typePine等。因此,当您调用 时wood.getBranch(),您正在Pine(例如)从WoodAPI/接口/角度查看。

但是,对象本身是PineOak等,因此将getBranch()调用对这些特定对象的调用。这就是多态性。我可以从广泛的超类参考中获得无限种对象的特定行为。所以我可以Wood随着我的应用程序的发展添加更多的s,我的代码不需要改变。

沿着这些思路,请记住,如果您正在执行大量基于类的条件逻辑,那么您将完全错过面向对象语言的好处。只需坚持使用 C。要了解原因,想象一下为SequoiaPalm等添加类。您真的想为所有具有条件的方法添加更多条件吗?周末的工作量很大。

于 2013-10-19T16:55:29.457 回答
0

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

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

于 2013-10-19T16:43:24.677 回答
0

在你的情况下:

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

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

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

那就是你创建像wood tree = new Pine().

于 2013-10-19T16:46:59.880 回答