超类引用子类对象,显示与子类对象的子类引用相同的行为

时间:2014-07-17 14:58:54

标签: java object inheritance

java中的以下代码,当在elipse上运行时,即使我们替换

也会提供相同的输出
superclass s=new sub();

用,

sub s= new sub();

请注意,我们已经覆盖了方法。

输出是:

changed supermethod in sub class
num is sub class 5

代码:

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");
    }
}

请指出,以这两种方式创建子类对象有何不同。访问方法和变量会有什么不同吗? (我们的java老师说,访问方法和变量在两种情况下都会有所不同)

此外,静态方法会发生什么,例如main。我知道它是可继承的,但有人可以突出它在子类中的行为吗?

4 个答案:

答案 0 :(得分:16)

在Java中,所有非静态方法都是“虚拟”,这意味着它们基于底层对象的运行时类型,而不是指向该对象的引用类型。因此,在对象声明中使用哪种类型无关紧要,行为将是相同的。

声明的作用是,在编译时可见的方法。如果SubClassSuperClass没有的方法(让我们称之为subMethod()),那么您将对象构建为

SuperClass s = new SubClass();

然后,您只能调用SuperClass上可用的方法。也就是说,尝试调用s.subMethod()会给你一个编译时错误。但是,正如您所发现的那样,如果SuperClass中存在方法,但SubClass覆盖了方法,那么它将是将被执行的重写方法。

另一方面,静态方法不是虚拟的。运行以下代码

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");
        }
    }
}

打印出“SuperMethod”。但是,您应该很少关注static方法是非虚拟的,因为您不应该像上面那样通过对象引用来调用它们。你应该通过班级名称来呼叫他们:

SuperClass.method();

答案 1 :(得分:2)

我在这里通过一些修改重写你的代码。 请看一下这些变化。

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.");
    }
}

现在,当您创建这样的对象时:

superclass s1=new sub();

然后你可以调用所有被覆盖的方法,比如

s1.supermethod();
s1.method();

在这种情况下,将调用子类的方法。
你也可以调用那些没有被覆盖的超类方法,比如

s1.methodInsuper();

但是如果您尝试访问仅在子类中定义的方法,如

s1.methodInsub();

然后它将是一个编译时错误。


它是becoz s1属于Superclass类型。
如果您仍想在子类中调用该方法,则需要将s1类型转换为子类,如

Sub s = (Sub) s1;

之后你可以调用子类的方法 如果你创建一个像

这样的对象
Sub s2 = new Sub();

然后,您可以访问子类或超类中定义的任何方法。

早期创建的对象基本上用于实现" Run Time Ploymorphism"。
希望你得到答案。

答案 2 :(得分:1)

你正在创建sub的sub并将它分配给super的引用。如果你不这样做 1)第一种情况: -

superclass s=new sub();   
        s.supermethod();
        s.method();

在上面的情况下会调用sub的方法但是这两个方法也应该存在于超类中(如果不存在那么编译时错误)

2)第二种情况: -

sub s=new sub();   
    s.supermethod();
    s.method();

在这也是sub的方法,这些方法可能会或可能不会出现超级。

答案 3 :(得分:0)

让我们举一个例子: sup是A类对象的参考变量。和sub是B类对象的引用变量。让我们假设B扩展了A。所以,如果我们写" sup = sub;"或" sup = new B();"这个语句使我们能够获得两个类之间共同的属性。即:B继承的属性......我们使用这个技巧来检查B继承的属性并进行了更改。

相关问题