Java 为什么我能够访问父类中的子方法?

Java 为什么我能够访问父类中的子方法?,java,inheritance,Java,Inheritance,我在理解Java中的继承时遇到了一个问题:当我将子类转换回父类时,我能够访问子类的重写方法 例如,给出了以下两类: 父对象: public class Parent { public void whatAreYou() { System.out.println("parent"); } } public class Child extends Parent { @Override public void whatAreYou() {

我在理解Java中的继承时遇到了一个问题:当我将子类转换回父类时,我能够访问子类的重写方法

例如,给出了以下两类:

父对象:

public class Parent {
    public void whatAreYou() {
        System.out.println("parent");
    }
}
public class Child extends Parent {
    @Override
    public void whatAreYou() {
        System.out.println("child");
    }

    public void onlyChildrenCanDoThis() {
        //...
    }

}
        Child c = new Child();
        Parent p = c;
        p.whatAreYou();
child
和子类:

public class Parent {
    public void whatAreYou() {
        System.out.println("parent");
    }
}
public class Child extends Parent {
    @Override
    public void whatAreYou() {
        System.out.println("child");
    }

    public void onlyChildrenCanDoThis() {
        //...
    }

}
        Child c = new Child();
        Parent p = c;
        p.whatAreYou();
child
当我现在执行以下操作时:

public class Parent {
    public void whatAreYou() {
        System.out.println("parent");
    }
}
public class Child extends Parent {
    @Override
    public void whatAreYou() {
        System.out.println("child");
    }

    public void onlyChildrenCanDoThis() {
        //...
    }

}
        Child c = new Child();
        Parent p = c;
        p.whatAreYou();
child
我得到这个输出:

public class Parent {
    public void whatAreYou() {
        System.out.println("parent");
    }
}
public class Child extends Parent {
    @Override
    public void whatAreYou() {
        System.out.println("child");
    }

    public void onlyChildrenCanDoThis() {
        //...
    }

}
        Child c = new Child();
        Parent p = c;
        p.whatAreYou();
child
这对于我理解Java中的继承是非常奇怪的。我希望得到一个
parent
输出,因为我将子类缩小到父类,这样我就可以访问父类的变量和方法

这是使用
p.onlyChildrenCanDoThis()
,因为我无法访问它,因为它没有在父类中实现


…但是对于被覆盖的方法,Java不会这样做这是为什么?

由于行
父级p=c,输出保持原样

想象一下:

class Car {
    public void whatAreYou() {
        System.out.println("Car");
    }
}

class Cadillac extends Car {
    public void whatAreYou() {
        System.out.println("Caddillac");
    }
}
如果你现在说

Cadillac coolCar = new Cadillac();
Car testCar = coolCar;
testCar.whatAreYou();
很明显,输出是“凯迪拉克”,不是吗?以下是您看待继承的方式:

凯迪拉克的物体总是汽车。汽车对象可以是凯迪拉克

由于我显式地将凯迪拉克参考
coolCar
设置为指向凯迪拉克的一个对象,并且将汽车参考
testCar
设置为指向同一个对象,因此我们得到了输出“凯迪拉克”

更明显的是,你甚至可以说

Car coolCar = new Cadillac();
Car testCar = coolCar;
testCar.whatAreYou();

由于行
parent p=c,输出保持原样

想象一下:

class Car {
    public void whatAreYou() {
        System.out.println("Car");
    }
}

class Cadillac extends Car {
    public void whatAreYou() {
        System.out.println("Caddillac");
    }
}
如果你现在说

Cadillac coolCar = new Cadillac();
Car testCar = coolCar;
testCar.whatAreYou();
很明显,输出是“凯迪拉克”,不是吗?以下是您看待继承的方式:

凯迪拉克的物体总是汽车。汽车对象可以是凯迪拉克

由于我显式地将凯迪拉克参考
coolCar
设置为指向凯迪拉克的一个对象,并且将汽车参考
testCar
设置为指向同一个对象,因此我们得到了输出“凯迪拉克”

更明显的是,你甚至可以说

Car coolCar = new Cadillac();
Car testCar = coolCar;
testCar.whatAreYou();

你现在要处理的是
c
被实例化为
new child()
,这就是为什么将
child
作为输出。
p
属于
parent
类型的事实并没有改变这一事实,它仍然指向
child

的实例
c
被实例化为
new child()
,这就是为什么将
child
作为输出。
p
属于
parent
类型的事实并没有改变这一事实,它仍然指向
child

的实例

child c=新的child()

您创建了子类的对象并将其引用指定给c

父母p=c

在这里,您已将子对象的引用复制到p。请记住,对象仍然是子对象而不是父对象

p、 whatAreYou()

这里你称之为whatAreYou方法。您正在使用指向子对象的引用变量p调用此函数。因此将调用child的方法。

另一种解释


以下是您所做的

child c=新的child()

您创建了子类的对象并将其引用指定给c

父母p=c

在这里,您已将子对象的引用复制到p。请记住,对象仍然是子对象而不是父对象

p、 whatAreYou()

这里你称之为whatAreYou方法。您正在使用指向子对象的引用变量p调用此函数。因此将调用child的方法。

另一种解释


而不是
Car.whatAreYou()?我不会称之为“明显的”,因为
汽车
当然“仍然”是
凯迪拉克
,但是
汽车
对象不能使用任何
凯迪拉克
变量和方法。或者举个例子:根据您的解释,家长应该仍然能够调用
p.onlyChildrenCanDoThis()
,因为(正如您所说)“
p
仍然是
child
”。@Robert您可以访问的方法是通过引用的类型定义的,在我的例子中,
testCar
被定义为
Car
。如果实际对象属于子类,并且该子类重写了任何方法,则可以访问这些方法,但不能访问引用类型(在本例中也是
Car
)中未定义的其他方法,而不是
Car.whatAreYou()?我不会称之为“明显的”,因为
汽车
当然“仍然”是
凯迪拉克
,但是
汽车
对象不能使用任何
凯迪拉克
变量和方法。或者举个例子:根据您的解释,家长应该仍然能够调用
p.onlyChildrenCanDoThis()
,因为(正如您所说)“
p
仍然是
child
”。@Robert您可以访问的方法是通过引用的类型定义的,在我的例子中,
testCar
被定义为
Car
。如果实际对象属于某个子类,并且该子类重写了任何方法,则您可以访问这些方法,但不能访问引用类型中未定义的其他方法(在本例中,也是
Car
)简短回答:非静态方法在运行时调度。否则无法使用方法重写。简短回答:非静态方法在运行时调度。否则,您不能使用任何方法重写。但是根据您的解释,我仍然可以调用
p.onlyChildrenCanDoThis()
,因为
p
只是对
c
的引用……不,您不能,因为p是父对象的引用变量,它不包含唯一的childrencandoth