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示例中。为什么呢?
答案 0 :(得分:5)
因为即使Integer
是Object
,Object
也不是Integer
,因此它没有Integer
的方法,只有{ {1}}的
引用的类型,而不是引用的对象的类型,确定可以执行操作。
他们的意思是,即使引用的对象包含更多功能,如果引用的类型与对象的类型不同,那么只有它们的功能参考类型将可用。
以下内容:
Object
Object aThing = new Integer(25);
的类型声明为aThing
。即使实现包含的内容不止于此,实现包含的任何其他内容都不再可见,因为变量的类型不是Object
,而是Integer
。 Object
和Object
都有共同的方法,但是从现在开始您只能访问Integer
提供的方法,因为除了您之外没有其他人知道这实际上是{{1} },而不仅仅是Object
。
在第二个示例中,它们表示即使Integer
和Object
都有共同的方法,当您调用其中一个方法时,也会调用实际类型的方法。因此,在这种情况下,如果您在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;
}
,因为Notebook
是showStatistics(n);
。它可以调用Notebook
的{{1}}方法,因为任何Notebook
都有该方法。当它调用它时,它会收到Computer
因为Notebook
会覆盖getInstalledOperatingSystems()
的实现。但是Computer
将无法调用1
提供的任何其他方法,因为它不知道它正在传递Notebook
。尽管如此,它有一个Computer
,它不知道showStatistics()
没有的任何其他方法。
你可以用Notebook
代替它,或者明天你可以创建Notebook
扩展Computer
或扩展Computer
类Desktop
}。你也可以发送它。但GamingComputer
无法访问任何Desktop
特定的专业方法,因为Server
{ }}。在编写Computer
时甚至没有发明它。
这与声明即使showStatistics()
始终为Server
,showStatistics()
也不总是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();