Java 对子类对象的超类引用显示与对子类对象的子类引用相同的行为
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24807029/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Superclass reference to subclass object showing same behaviour as subclass reference to subclass object
提问by nishantbhardwaj2002
The following code in java, when run on elipse, gives same output even if we replace
java中的以下代码,当在 elipse 上运行时,即使我们替换它也会给出相同的输出
superclass s=new sub();
with,
和,
sub s= new sub();
Note that we have overridden methods.
请注意,我们已经覆盖了方法。
Output is:
输出是:
changed supermethod in sub class
num is sub class 5
Code:
代码:
public class superclass {
int num=2;
public static void main(String str[]){
superclass s=new sub();
//HERE: nothing changes if we write, sub s=new sub();
s.supermethod();
s.method();
}
void supermethod(){
System.out.println("supermethod as in superclass");
}
void method(){
System.out.println("num in superclass "+num);
}
}
class sub extends superclass{
int num=5;
void method(){
System.out.println("num is sub class "+num);
}
void supermethod(){
System.out.println("changed supermethod in sub class");
}
}
Please point out, what are the differences in creating a sub class object in these two ways. And will there be any difference in accessing methods and variables? (our java teacher says, accessing method and variables will be different in both cases)
请指出,这两种方式创建子类对象有什么区别。并且在访问方法和变量上会有什么区别吗?(我们的java老师说,两种情况下访问方法和变量都会不同)
Also, what happens to the static methods, like main. Tough i know it is inheritable, but can someone highlight its behavior in sub classes?
另外,静态方法会发生什么,比如 main. 我知道它是可继承的,但是有人可以在子类中突出显示它的行为吗?
采纳答案by matt forsythe
In Java, all non-static methods are "virtual", meaning that they are based on the runtime type of the underlying object rather than the type of the reference that points to that object. Therefore, it doesn't matter which type you use in the declaration of the object, the behavior will be the same.
在 Java 中,所有非静态方法都是“虚拟的”,这意味着它们基于底层对象的运行时类型,而不是指向该对象的引用类型。因此,无论您在对象声明中使用哪种类型,行为都是相同的。
What the declaration does affect, is the methods that are visible at compile-time. If SubClass
has a method that SuperClass
does not (let's call it subMethod()
), and you construct your object as
声明确实影响的是在编译时可见的方法。如果SubClass
有一个SuperClass
没有的方法(让我们称之为subMethod()
),并且您将对象构造为
SuperClass s = new SubClass();
Then you will only be able to call methods on it that are available on SuperClass
. That is, attempting to call s.subMethod()
will give you a compile time error. But, as you have discovered, if there methods are present in SuperClass
, but overridden by SubClass
, it will be the overridden method that will be executed.
然后,您将只能在其上调用SuperClass
. 也就是说,尝试调用s.subMethod()
会给你一个编译时错误。但是,正如您所发现的,如果存在于SuperClass
中但被SubClass
覆盖的方法,则将执行被覆盖的方法。
Static methods, on the other hand, are not virtual. Running the code below
另一方面,静态方法不是虚拟的。运行下面的代码
public class StaticTest {
public static void main(String[] args) {
SuperClass s = new SubClass();
s.method(); // bad idea - calling static method via an object reference
}
public static class SuperClass {
public static void method() {
System.out.println("SuperMethod");
}
}
public static class SubClass extends SuperClass {
public static void method() {
System.out.println("SubMethod");
}
}
}
prints out "SuperMethod". You should rarely care, however, that static
methods are non-virtual because you should never call them via an object reference as I have done above. You should call them via the class name:
打印出“超级方法”。然而,您应该很少关心static
方法是非虚拟的,因为您永远不应该像我上面所做的那样通过对象引用调用它们。您应该通过类名调用它们:
SuperClass.method();
回答by kb4shubham
I'm rewriting your code here with some modification. Please look at the changes.
我正在这里重写您的代码并进行一些修改。请看变化。
public class superclass {
int num=2;
public static void main(String str[]){
superclass s=new sub();
//HERE: nothing changes if we write, sub s=new sub();
s.supermethod();
s.method();
}
...
...
//This method is not overridden.
void methodInSuper(){
System.out.prinln("method not overridden.");
}
}
class sub extends superclass{
int num=5;
...
...
//This is only in subclass.
void methodInSub(){
System.out.println("method only in subclass.");
}
}
Now when you are creating an object like this:
现在,当您创建这样的对象时:
superclass s1=new sub();
Then you can call all the overridden methods like
然后你可以调用所有重写的方法,比如
s1.supermethod();
s1.method();
In this case the methods of subclass will be called.
you can also call methods of superclass those are not overridden like
在这种情况下,将调用子类的方法。
您还可以调用未覆盖的超类方法,例如
s1.methodInsuper();
but if you try to access method defined only in subclass like
但是如果您尝试访问仅在子类中定义的方法,例如
s1.methodInsub();
then it will be a compile time error.
那么这将是一个编译时错误。
It is becoz s1 is of type Superclass.
If you still want to call the method in subclass then you need to typecast s1 to subclass like
这是因为 s1 是 Superclass 类型。
如果您仍然想在子类中调用该方法,则需要将 s1 类型转换为子类,例如
Sub s = (Sub) s1;
After that you can call the method of the subclass.
And if you create an object like
之后就可以调用子类的方法了。
如果你创建一个像
Sub s2 = new Sub();
Then you can access any methods defined in subclass or superclass.
The earlier creation of object is basically used for implementing "Run Time Ploymorphism".
Hope you got your answer.
然后您可以访问子类或超类中定义的任何方法。
较早的对象创建主要用于实现“运行时多态”。
希望你得到你的答案。
回答by Govinda Sakhare
you are creating Object of sub and assigning it to super's reference.if you dont 1)first case:-
您正在创建 sub 的对象并将其分配给 super 的引用。如果您不 1) 第一种情况:-
superclass s=new sub();
s.supermethod();
s.method();
in above case methods of sub will be called but these two method should be present in superclass also(if not present then compile time error)
在上述情况下 sub 的方法将被调用,但这两个方法也应该存在于超类中(如果不存在则编译时错误)
2)second case:-
2)第二种情况:-
sub s=new sub();
s.supermethod();
s.method();
in this also methods of sub will be ,these method may or may not be present super.
在这也是 sub 的方法,这些方法可能会或可能不会出现超级。
回答by Nawfal
let's take an example: sup is a reference variable for a class A's objects. and sub is a reference variable for a class B's objects. let's suppose B extends A . so if we write "sup = sub;" or "sup = new B();" this statement enables us to get the attributes that are common between the 2 classes . i.e : the attributes that were inherited by B ... we use this trick to check for attributes inherited by B and were changed.
让我们举个例子:sup 是 A 类对象的引用变量。而 sub 是 B 类对象的引用变量。假设 B 扩展了 A 。所以如果我们写“sup = sub;” 或“sup = new B();” 这个语句使我们能够获得两个类之间的共同属性。即:由 B 继承的属性......我们使用这个技巧来检查由 B 继承并被更改的属性。