没有“抽象”的Java中的运行时多态性?(Run-time Polymorphism in Java without “abstract”?)
我正在阅读官方的Oracle教程,其中介绍了多态性的概念,以及3个类的类层次结构的示例; 自行车是超类,MountainBike和RoadBike是2个子类。
它显示了2个子类如何重写在Bicycle中声明的方法“printDescription”,通过声明它的不同版本。
最后,在最后,教程提到Java虚拟机(JVM)为每个变量中引用的对象调用适当的方法。
但是,关于多态性的教程没有提到“抽象”类和方法的概念。 除非将Bicycle中的printDescription()声明为“abstract”,否则如何实现运行时多态性? 我的意思是,在这个例子中,基于什么提示,编译器决定在编译时不将方法调用绑定到引用类型,并认为它应该留给JVM在运行时处理?
以下是使用的示例:
public class Bicycle { public int cadence; public int gear; public int speed; public Bicycle(int startCadence, int startSpeed, int startGear) { gear = startGear; cadence = startCadence; speed = startSpeed; } public void setCadence(int newValue) { cadence = newValue; } public void setGear(int newValue) { gear = newValue; } public void applyBrake(int decrement) { speed -= decrement; } public void speedUp(int increment) { speed += increment; } public void printDescription(){ System.out.println("\nBike is " + "in gear " + this.gear + " with a cadence of " + this.cadence + " and travelling at a speed of " + this.speed + ". "); } } public class MountainBike extends Bicycle { private String suspension; public MountainBike( int startCadence, int startSpeed, int startGear, String suspensionType){ super(startCadence, startSpeed, startGear); this.setSuspension(suspensionType); } public String getSuspension(){ return this.suspension; } public void setSuspension(String suspensionType) { this.suspension = suspensionType; } public void printDescription() { super.printDescription(); System.out.println("The " + "MountainBike has a" + getSuspension() + " suspension."); } } public class RoadBike extends Bicycle{ private int tireWidth; public RoadBike(int startCadence, int startSpeed, int startGear, int newTireWidth){ super(startCadence, startSpeed, startGear); this.setTireWidth(newTireWidth); } public int getTireWidth(){ return this.tireWidth; } public void setTireWidth(int newTireWidth){ this.tireWidth = newTireWidth; } public void printDescription(){ super.printDescription(); System.out.println("The RoadBike" " has " + getTireWidth() + " MM tires."); } } public class TestBikes { public static void main(String[] args){ Bicycle bike01, bike02, bike03; bike01 = new Bicycle(20, 10, 1); bike02 = new MountainBike(20, 10, 5, "Dual"); bike03 = new RoadBike(40, 20, 8, 23); bike01.printDescription(); bike02.printDescription(); bike03.printDescription(); } }
I was going over the official Oracle tutorial where it introduces the idea of polymorphism with the example of a class hierarchy of 3 classes; Bicycle being the superclass, and MountainBike and RoadBike being 2 subclasses.
It shows how the 2 subclasses override a method "printDescription" declared in Bicycle, by declaring different versions of it.
And finally, toward the end, the tutorial mentions the Java Virtual Machine (JVM) calls the appropriate method for the object that is referred to in each variable.
But, nowhere does the tutorial on polymorphism mention the concept of "abstract" classes and methods. How is run-time polymorphism achieved unless printDescription() in Bicycle is declared "abstract"? I mean, given this example, based on what hints does the compiler decide not to bind method invocation to the reference type at compile time, and think that it should leave it for the JVM to deal with at run-time?
Below is the example used:
public class Bicycle { public int cadence; public int gear; public int speed; public Bicycle(int startCadence, int startSpeed, int startGear) { gear = startGear; cadence = startCadence; speed = startSpeed; } public void setCadence(int newValue) { cadence = newValue; } public void setGear(int newValue) { gear = newValue; } public void applyBrake(int decrement) { speed -= decrement; } public void speedUp(int increment) { speed += increment; } public void printDescription(){ System.out.println("\nBike is " + "in gear " + this.gear + " with a cadence of " + this.cadence + " and travelling at a speed of " + this.speed + ". "); } } public class MountainBike extends Bicycle { private String suspension; public MountainBike( int startCadence, int startSpeed, int startGear, String suspensionType){ super(startCadence, startSpeed, startGear); this.setSuspension(suspensionType); } public String getSuspension(){ return this.suspension; } public void setSuspension(String suspensionType) { this.suspension = suspensionType; } public void printDescription() { super.printDescription(); System.out.println("The " + "MountainBike has a" + getSuspension() + " suspension."); } } public class RoadBike extends Bicycle{ private int tireWidth; public RoadBike(int startCadence, int startSpeed, int startGear, int newTireWidth){ super(startCadence, startSpeed, startGear); this.setTireWidth(newTireWidth); } public int getTireWidth(){ return this.tireWidth; } public void setTireWidth(int newTireWidth){ this.tireWidth = newTireWidth; } public void printDescription(){ super.printDescription(); System.out.println("The RoadBike" " has " + getTireWidth() + " MM tires."); } } public class TestBikes { public static void main(String[] args){ Bicycle bike01, bike02, bike03; bike01 = new Bicycle(20, 10, 1); bike02 = new MountainBike(20, 10, 5, "Dual"); bike03 = new RoadBike(40, 20, 8, 23); bike01.printDescription(); bike02.printDescription(); bike03.printDescription(); } }
原文:https://stackoverflow.com/questions/12709033
最满意答案
如果您希望在启动场景时运行它,则需要将其附加到GameObject。 创建为空并将其作为组件附加。
您要在start上运行的代码应位于:
void Awake {//Your code here}
或void Start{//Your code here}
函数。一旦实例化类就调用Start,并在场景启动时调用Awake。 取决于你想要它在调用堆栈中的位置,但在你的情况下,我认为它将基本上做同样的事情。
If you want it to run when you start the scene you need to attach it to a GameObject. Create empty and attach it as a component.
The code that you want to run on start should be in the:
void Awake {//Your code here}
orvoid Start{//Your code here}
functions.Start is called as soon as the class is instantiated and Awake is called when the scene is started. Depends where you want it in the call stack, but in your case i think it will do essentially the same thing.
相关问答
更多-
TCP/IP模型是一个________。[2023-05-19]
a -
下列中不属于面向对象的编程语言的是?[2022-05-30]
a -
请删除; (如果条件之后的话) GUI.Label(new Rect(Screen.width / 2 - 40, 300, 80, 30), "Score: " + score); if (GUI.Button(new Rect(Screen.width / 2 - 30, 350, 60, 30), "Retry?")) //---->; { Application.LoadLevel(0); } please delete ; (located after if condition) GUI ...
-
如果您希望在启动场景时运行它,则需要将其附加到GameObject。 创建为空并将其作为组件附加。 您要在start上运行的代码应位于: void Awake {//Your code here}或void Start{//Your code here}函数。 一旦实例化类就调用Start,并在场景启动时调用Awake。 取决于你想要它在调用堆栈中的位置,但在你的情况下,我认为它将基本上做同样的事情。 If you want it to run when you start the scene you ne ...
-
未来的提示,不要为暂停项操作Time.timeScale。 我从困难的方式吸取了教训,它做了一些时髦的事情。 最好的办法是保存所有对象的状态,或者使用静态公共变量或模拟状态机的类。 如果暂停状态(全局静态),则跳过Update()LateUpdate()FixedUpdate()中的内容。 你得到漂移。 My solution is that I relased that, I reset Time.timeScale, firstly set "0", then set again 1 void Star ...
-
Unity中C#中的数组错误(Array error in C# for Unity)[2022-10-05]
当阵列仅分配模拟阵列交互具有自动增长功能的复杂类型时,阵列具有固定大小。 检查您正在复制原始阵列内容的目标阵列的容量。 我不确定ToBuiltIn方法做了什么,但它必须创建一个新数组作为源的副本(顺便说一下,你的数据可能已经在数组中,通过调试来检查),容量设置为总数数组中的项目可以是1或0。 检查变量并调试代码以查看数组的长度和容量。 更新 (来自更新的代码) 调用Add Item方法时,不会初始化Contents数组。 为了说清楚我已经重写了你粘贴的代码我没有你正在使用的所有类,所以我没有测试或检查它构建 ... -
Unity3d脚本似乎在一个场景中工作,但不在另一个场景中(Unity3d script seems to work in one scene but not another)[2022-03-10]
通过将问题场景中的所有资产复制到新场景来解决此问题。 现在它就像一个魅力。 Fixed the problem by copying over all of the assets in the problem scene to a new scene. Now it works like a charm. -
发生错误是因为您正在尝试获取内存中程序集的位置(即时创建的程序集),并且这些程序集不在任何位置。 如果你想避免这个错误尝试这样的事情: this.assemblyReferences = domain.GetAssemblies().Select(a => { try{ return a.Location; }catch{ return null; } }).Where(s => s != null).ToArray(); 编辑: 正如Jon Skeet指出的那样,可以使用“IsDynami ...
-
我解决了:而不是SceneManager.LoadScene(0)需要使用:EditorSceneManager.OpenScene(scene.path); I resolved: instead SceneManager.LoadScene(0) need use : EditorSceneManager.OpenScene(scene.path);
-
在卸载(销毁)场景时销毁BannerView: using UnityEngine; using System.Collections; using GoogleMobileAds.Api; public class Banner : MonoBehaviour { private BannerView bannerView; void Start() { bannerView = new BannerView ("************", AdSize.Banner ...