将子类保存为超类类型并在Java中使用其方法

将子类保存为超类类型并在Java中使用其方法,java,inheritance,subclass,superclass,Java,Inheritance,Subclass,Superclass,在下面的代码中,子类扩展了它的超类,并重写了它的方法,使用它调用子类特有的另一个方法,该方法使用子类的一个变量 然后程序将子类的一个实例存储到超类类型的变量中,然后调用其方法。然后,它像Subclass类型一样运行,调用子类特有的方法和变量。但是,不可能直接访问这些 class Superclass { void go() { System.out.println(0); } } class Subclass extends Superclass { i

在下面的代码中,子类扩展了它的超类,并重写了它的方法,使用它调用子类特有的另一个方法,该方法使用子类的一个变量

然后程序将子类的一个实例存储到超类类型的变量中,然后调用其方法。然后,它像Subclass类型一样运行,调用子类特有的方法和变量。但是,不可能直接访问这些

class Superclass {
    void go() {
        System.out.println(0);
    }
}

class Subclass extends Superclass {
    int i = 1;

    @Override
    void go() {
        run();
    }

    void run() {
        System.out.println(i);
    }
}

public class JavaApplication {
    public static void main(String[] args) {
        Superclass instance = new Subclass();

        instance.go();                 // outputs 1; it must have called run() and accessed i
        instance.run();                // causes compile-time error
        System.out.println(instance.i);// causes compile-time error
    }
}

一旦子类实例保存为类型超类,它仍然可以访问所有子类字段和方法。那么为什么我不能直接访问它们呢?

对于变量和静态方法,根据引用类型调用方法,而不是根据引用的对象调用方法


但是在实例方法的情况下,方法是根据被引用对象的类型调用的,而不是根据引用类型调用的

,因为引用类型是超类,并且不能保证被引用对象具有此方法。仅仅因为你知道他们在那里,并不意味着电脑可以保证他们会在那里。你试图做的就是所谓的,一般来说,这是一件非常糟糕的事情,可能意味着你的设计需要更仔细地考虑。在某些情况下这是不可避免的,但这些情况很少(特别是使用适当的泛型)可能重复。如果您知道引用类型的超类实际上是子类对象,您可以简单地将其转换为子类以引用子类的方法。这样做没有错(尽管有时更仔细的设计可以避免这种需要)是您需要的。除了OP的问题是子类方法甚至不能被引用,因为引用被声明为超类。