This question already has answers here:
Overriding member variables in Java ( Variable Hiding)

(11个答案)



Polymorphism with instance variables [duplicate]

(2个答案)


4年前关闭。




我有一个子类ScottishPerson,它继承自BritishPerson类。
class BritishPerson {
    public String name = "A british name";

    public void salute() {
        System.out.println("Good Morning!");
    }
}

class ScottishPerson extends BritishPerson {
    public String name = "A scottish name "; //Variable overriding
    public String clanName = "MacDonald";

    public void salute() //Method overriding
    {
        System.out.println("Madainn Mhath!");
    }

    public void warcry() {
        System.out.println("Alba Gu Brath!");
    }
}

class Driver {

    public static void main(String[] args) {
        ScottishPerson scottishPerson = new ScottishPerson(); //Created as a subclass, can always be upcasted.
        BritishPerson britishPerson = new BritishPerson(); //Created as the superclass, throws an error when downcasted.
        BritishPerson britishPersonUpcasted =
                new ScottishPerson(); //Created as the subclass but automatically upcasted, can be downcasted again.

        //Checking the methods and parameters of scottishPerson
        scottishPerson.salute();
        scottishPerson.warcry();
        System.out.println(scottishPerson.name);
        System.out.println(scottishPerson.clanName);

        //Checking the methods and parameters of britishPerson
        britishPerson.salute();
        System.out.println(britishPerson.name);

        //Checking the methods and parameters of britishPersonUpcasted
        britishPersonUpcasted.salute();
        System.out.println(britishPersonUpcasted.name);
    }
}

运行代码,这是输出。
Madainn Mhath!
Alba Gu Brath!
A scottish name
MacDonald
Good Morning!
A british name
Madainn Mhath!
A british name

这就是混乱所在。将ScottishPerson转换为BritishPerson会将变量名称更改为超类中定义的一个。仅存在于子类中的方法和变量(例如warcry()clanName)将被丢弃。但是,在向上转换的类上调用方法salute()仍然返回基于子类实现的字符串。

是因为我在创建对象britishPerson时仅初始化BritishPerson类,并且在创建对象britishPersonUpcasted时同时创建了BritishPerson类和ScottishPerson类,从而导致salute()方法的永久覆盖吗?

最佳答案

请看一下这个问题,以进一步了解上行和下行:

What is the difference between up-casting and down-casting with respect to class variable

我还举了一个查看向上行为的示例:

abstract class Animal
{
    public void saySomething()
    {
        System.out.println("Some Animal sound");
    }

    public abstract void getTheBall();
}

class Horse extends Animal
{
    public void saySomething()
    {
        System.out.println("Neigh Neigh");
    }

    public void getTheBall()
    {
        System.out.println("I won't, Try a dog, I am a Horse!");
    }
}

class Dog extends Animal
{
    public void saySomething()
    {
        System.out.println("woof woof, waon waon");
    }

    public void getTheBall()
    {
        System.out.println("huf huf, here it is!");
    }
}

public class Main
{
    public static void main (String [] args)
    {
        Dog dog = new Dog();
        Horse horse = new Horse();
        Animal animal = dog;
        Animal horseAnimal = new Horse();

        //upcasting
        Dog upcastedAnimal = upcastToDog(animal);
        dog.saySomething();
        dog.getTheBall();

        upcastedAnimal.saySomething();
        upcastedAnimal.getTheBall();

        horse.saySomething();
        horse.getTheBall();

        try {
            Dog upcastedDog = upcastToDog(horseAnimal);
        } catch (Exception ex){
            System.out.println(ex.getClass().getSimpleName() + ": Obviously a horse is not a dog!");
        }
    }

    public static Dog upcastToDog(Animal animal){
        return (Dog) animal;
    }
}

输出:
woof woof, waon waon
huf huf, here it is!
woof woof, waon waon
huf huf, here it is!
Neigh Neigh
I won't, Try a dog, I am a Horse!
ClassCastException: Obviously a horse is not a dog!

首先,如果试图强制转换不兼容的类型,java将抛出异常。

在可能进行强制转换的情况下,将始终从实际实例中调用重写的方法。在您的情况下,实例是ScottishPerson,因此即使您将其引用保存在BritishPerson中,也将在ScottishPerson上调用方法。

您可以在此处运行示例https://repl.it/B83f/3

在JLS中,这里包含“Narrowing Reference Conversion”,因为他的名字暗示仅引用是缩小或扩大(或上调或下调)而不是实例。

09-28 04:29