System.out.println("Data2="+a.data2);
这不能做,java是这样工作的
编译器查看您的左侧(变量),并据此知道它可以访问哪些方法(其中 data2 在您的变量所引用的类 A 中找不到),
但在运行时,JVM 在堆上查看真实创建的对象(通过“new”关键字),即
new B();
因此,它采用编译器选择的方法,并根据内存中的可用对象在运行时实现它
所以 ....
A a = new B();
你首先声明一个你想要的任何类型的变量(A),这样你就可以访问它的任何可能的方法或变量
并且编译器正在等待您将任何通过 IS-A 测试的对象分配给此变量类型,并且由于 B 扩展了 A,因此它是 IS-A“A”,任何子类 IS-A 超类
所以编译器接受这个赋值
此技术用于使同一方法 throw 子类的不同实现(使用)受益,例如:
这些是在体育场进行的运动种类和门票价格
class Sport{ int getTicketPrice(){ return 0;}}
class Basketball extends Sport{ int getTicketPrice(){return 10;}}
class Football extends Sport{ int getTicketPrice(){return 20;}}
假设这是体育场售票系统的一部分,并且有一个班级根据人们想参加的运动类型来确定票价,所以它会有这样的方法
class Tickets{ int getPrice(Sport sport){return sport.getTicketPrice();}}
如果没有多态性(IS-A / 继承),我们将需要创建 3 个门票类,每个类都有一个 getPrice() 方法,该方法将我们的 3 个类(运动、篮球、足球)中的每一个作为参数,但是
编译器将允许您使用 Sport 类的任何子类,因为它确定 Sport 类(及其所有子类)具有名为“getTicketPrice()”的方法,并且如果子类没有覆盖(更改实现/使用这个方法和这个例子一样),原来的方法将被实现
所以,编译器端检查方法,JVM决定这个方法的真实结果,回到我们的例子,我们将有一个类来运行系统的这一部分,一个类负责获取运动的类型,以及检查它的票价,然后将其显示给用户,因此该课程的一部分将是
class BasketballBoxOffice{
Tickets tickets = new Tickets();
Sport sport = new Basketball();
// this is a method that runs when ever the Tickets Seller clicks
// on Print Ticket Button on the Screen
void printTicket(){
// some code
System.out.println(tickets.getPrice(sport));
// some code
}
// more code
}
现在使用相同的系统,在这个体育场足球区的票房上,你不需要新的课程,而只需要一个“多态性”
class FootballBoxOffice{
Tickets tickets = new Tickets();
Sport sport = new Football(); // thats all the difference
// this is a method that runs when ever the Tickets Seller clicks
// on Print Ticket Button on the Screen
void printTicket(){
// some code
System.out.println(tickets.getPrice(sport));
// some code
}
// more code
}
由于多态性(继承),无需更改代码的任何内容,只需子类化任何类,并为其方法创建自己的实现,并使用它
希望这不是我的愚蠢解释