为什么多态在这种情况下不起作用?

时间:2012-10-14 23:13:00

标签: java polymorphism

Object aThing = new Integer(25);

方法调用aThing.intValue()是编译器错误。为什么多态在这种情况下不起作用?

在我的教科书中还有一个相关的陈述有点令人费解:

  

引用的类型,而不是引用的对象的类型,确定可以执行操作。

你能简要说明一下吗?

Computer[] labComputers = new Computer[10];与多态性一起工作的地方

public class Computer {
    int ram;
    public Computer(int rm){
        ram= rm;
    }
    public String toString(){
        String result = "ram is " + ram;
        return result;
    }
}


public class Notebook extends Computer{
int size;
public Notebook(int rm, int sz){
    super(rm);
    size = sz;
}
@Override
    public String toString(){
        String result = super.toString() + " size is " + size;
        return result;
    }

}

: 我相信在中间某处,会有

labComputer[1] = new Notebook(2,15);
labComputer[2] = new Computer(2);

对于方法调用labComputers[1].toString(),多态性可确保调用正确的toString。我认为labComputer[1] = new Notebook(2,15);相当于Object o = new Integer(25);。但是多态性适用于我的计算机示例,而不是在Object-Integer示例中。为什么呢?

4 个答案:

答案 0 :(得分:5)

因为即使IntegerObjectObject也不是Integer,因此它没有Integer的方法,只有{ {1}}的


  

引用的类型,而不是引用的对象的类型,确定可以执行操作。

他们的意思是,即使引用的对象包含更多功能,如果引用的类型与对象的类型不同,那么只有它们的功能参考类型将可用。

以下内容:

Object

Object aThing = new Integer(25); 的类型声明为aThing。即使实现包含的内容不止于此,实现包含的任何其他内容都不再可见,因为变量的类型不是Object,而是IntegerObjectObject都有共同的方法,但是从现在开始您只能访问Integer提供的方法,因为除了您之外没有其他人知道这实际上是{{1} },而不仅仅是Object


在第二个示例中,它们表示即使IntegerObject都有共同的方法,当您调用其中一个方法时,也会调用实际类型的方法。因此,在这种情况下,如果您在Object上致电Integer,则会调用toString()的{​​{1}}方法,而不是aThing。因此,这只是一个访问问题。您将其声明为Integer的事实并不意味着您将获得toString()的方法来响应调用,它只表示Object中存在的任何方法和不在Object中的人将无法使用。


示例:

Object

现在让我们创建一个Integer

Object

假设您有以下方法:

class Computer {
    public int getInstalledOperatingSystems() { return 3; }
}

class Desktop extends Computer {
    public String getShapeOfCase() { ... }
}

class Notebook extends Computer {
    public int getInstalledOperatingSystems() { return 1; }
    public String getBrand() { ... }
    public void closeLid() { ... }
}

如果您使用上面定义的Notebook来调用此方法:

Notebook n = new Notebook();

然后该方法将收到public String showStatistics(Computer computer) { result = "Operating systems: " + computer.getInstalledOperatingSystems(); return result; } ,因为NotebookshowStatistics(n); 。它可以调用Notebook的{​​{1}}方法,因为任何Notebook都有该方法。当它调用它时,它会收到Computer因为Notebook会覆盖getInstalledOperatingSystems()的实现。但是Computer将无法调用1提供的任何其他方法,因为它不知道它正在传递Notebook。尽管如此,它有一个Computer,它不知道showStatistics()没有的任何其他方法。

你可以用Notebook代替它,或者明天你可以创建Notebook扩展Computer或扩展ComputerDesktop }。你也可以发送它。但GamingComputer无法访问任何Desktop特定的专业方法,因为Server { }}。在编写Computer时甚至没有发明它。

这与声明即使showStatistics()始终为ServershowStatistics()也不总是Server


你可以检查一下。因此,如果您知道您可能会传递showStatistics(),而不仅仅是计算机,那么您可以查找它,甚至可以调用Server的方法,但是你必须确保您正在查看Computer

Computer

答案 1 :(得分:5)

它不起作用,因为您的变量来自Object类,因此您只能使用Object类中的方法。如果要将其用作Integer,则应首先执行(向下)类型转换:

Integer aInteger = (Integer)aThing;
//it could maybe work
aInteger.intValue();

现在,为什么可能工作?因为如果类型转换不起作用,向下转换可能抛出ClassCastException。

根据您的示例,我将发布一个基本代码,以显示多态性的工作原理:

class Animal {
    public void move() {
        System.out.println("I'm an animal and I can move.");
    }
}

class Cat extends Animal {
    //this means a Cat would change the move behavior from the Animal instance
    @Override
    public void move() {
        System.out.println("I'm a cat and I can move.");
    }
}

class Dog extends Animal {
    //this means a Cat would change the move behavior from the Animal instance
    @Override
    public void move() {
        System.out.println("I'm a dog and I like to run.");
    }
    public void bark() {
        System.out.println("I can bark!");
    }
}

public class AnimalTest {
    public static void main(String[] args) {
         //it will take the behavior of the Animal class reference
         Animal animal = new Animal();
         //it will take the behavior of the Cat class reference
         Animal cat = new Cat();
         //it will take the behavior of the Dog class reference
         Animal dog = new Dog();
         //this will invoke the Animal#move method
         animal.move();
         //this will invoke the Cat#move method because it was overriden in the Cat class
         cat.move();
         //this will invoke the Dog#move method because it was overriden in the Dog class
         dog.move();
         //this line won't compile if uncommented because not all animals can bark.
         //dog.bark();
         //if you want to make the dog barks, then you should use the downcasting
         ((Dog)dog).bark();
         //note that this will only work for Dog class reference, not for any other class
         //uncomment this line and the code will compile but throw a ClassCastException
         //((Dog)cat).bark();
    }
}

答案 2 :(得分:2)

这样想,狗是一个对象,狗类可能有像

这样的方法

dog.bark()

如果您将Dog的层次结构强制转换为Object,则它会变得不那么具体。

Object o = dog;

现在你所知道的是o是一个物体,你不知道什么样的物体,因此你不知道这个物体是否可以吠叫。

当您向上移动层次结构时,您几乎总是会因为对所拥有的内容不太具体而失去功能。

答案 3 :(得分:0)

编译器需要被告知对象应该是什么类型,因此它可以查找类并查看该方法是否合法。

所以你可以说Object aThing = new Integer(25);但是你想说int thingValue = (Integer)aThing.intValue();

如果您的MySubClass对象是MyClass的子类,并且您想调用MyClass中定义的方法(即使在MySubClass中重新实现),您可以说:

Object myObject = new MySubClass();
int someValue = (MyClass)myObject.methodInMyObject();