Java 为什么向上转换类不会更改重写的方法?

Java 为什么向上转换类不会更改重写的方法?,java,inheritance,subclass,superclass,upcasting,Java,Inheritance,Subclass,Superclass,Upcasting,我有一个子类ScottishPerson,它继承自类BritishPerson class BritishPerson { public String name = "A british name"; public void salute() { System.out.println("Good Morning!"); } } class ScottishPerson extends BritishPerson { public String

我有一个子类
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
将被丢弃。但是,在升级的类上调用方法
sallet()
,仍然会返回基于子类实现的字符串


是因为当我创建对象
britishPerson
时,我只初始化了
britishPerson
类,而当我创建对象
britishPersonUpcasted
时,我创建了
britishPerson
类和
ScottishPerson
类,这导致了
Salet()的永久重写吗
方法

您实际调用方法的对象属于
ScottishPerson
,因此在编译时它会检查引用变量,但在运行时它总是执行属于对象的方法,而不是引用持有它的对象。运行时多态性实际上是这个概念的基础。

  • 对静态字段、实例字段和静态方法的访问取决于参考变量的类,而不是变量指向的实际对象
  • 请记住,成员变量是隐藏的,而不是重写的
  • 这与实例方法的情况相反。
    对于实例方法,调用对象的实际类的方法
考虑下面的例子

    class ABCD {
        int x = 10;
        static int y = 20;

        public String getName() {
            return "ABCD";
        }
    }

    class MNOP extends ABCD {
        int x = 30;
        static int y = 40;

        public String getName() {
            return "MNOP";
        }
    }

    public static void main(String[] args) {

      System.out.println(new MNOP().x + ", " + new MNOP().y);

      ABCD a = new MNOP();
      System.out.println(a.x); // 10
      System.out.println(a.y); // 20
      System.out.println(a.getName()); // MNOP
    }
在您的场景中,
britishPersonUpcasted
对象的
name
属性被
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);
    }
}

希望这有帮助。

变量在Java中不是多态的。子类中声明的同一变量不会重写超类中的值

要反映与super类关联的值,需要将其传递给构造函数,并使用super关键字设置super类变量。这样:

  public ScottishPerson(String name) {
    super.name = name;
    this.name = name;
  }
这是我修改过的代码

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 ScottishPerson() {
    // TODO Auto-generated constructor stub
  }

  public ScottishPerson(String name) {
    super.name = name;
    this.name = name;
  }

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

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

}

public class Driver {



  public static void main(String[] args) {
    // TODO Auto-generated method stub


    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("Another scottish name"); //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);
  }

}

您可以在子类中声明一个与超类中的字段同名的字段,从而将其隐藏(不推荐)


即使您需要它,您也可以通过
super
关键字访问它请查看此问题,以了解更多关于向上和向下播放的信息:

我还举了一个观察上抛行为的例子:

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,因此方法将在ScottishPerson上调用,即使您在英国人中持有它的引用

您可以在这里运行这个示例


在JLS中,它包含在这里,正如他的名字所暗示的那样,只有引用被缩小或扩大(或上移或下移),而不是实例

但是为什么字段
name
指向
BritishPerson
。多态性是方法的概念,而不是变量的概念。我正在学习类型转换的概念,我无法理解您在
upcasttolog
方法中将父类对象(动物)更改为子类对象(狗),然而你称之为向上投射。为什么?从父类到子类的强制转换不是称为“向下转换”?对不起,如果我错了。