重载是编译时多态。真? [英] Overloading is compile-time polymorphism. Really?

查看:152
本文介绍了重载是编译时多态。真?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我确实知道覆盖和重载之间的语法差异。我也知道覆盖是运行时多态,重载是编译时多态。但我的问题是:重载是否真的是编译时多态?方法调用是否真的在编译时解决了?。为了澄清我的观点,让我们考虑一个示例类。

I do know the syntactical difference between overriding and overloading. And I also know that overriding is run-time polymorphism and overloading is compile-time polymorphism. But my question is: "Is overloading is really compile-time polymorphism? Is the method call really solving at compile time?". To clarify my point, let's consider an example class.

public class Greeter {
    public void greetMe() {
        System.out.println("Hello");
    }

    public void greetMe(String name) {
        System.out.println("Hello " + name);
    }

    public void wishLuck() {
        System.out.println("Good Luck");
    }
}

由于所有方法 greetMe(),greetMe(String name),wishLuck()是公共的,它们都可以被覆盖(包括重载的),对吧?例如,

Since all of the methods greetMe(), greetMe(String name), wishLuck() are public, they all can be overriden(including overloaded one), right? For example,

public class FancyGreeter extends Greeter {
    public void greetMe() {
        System.out.println("***********");
        System.out.println("*  Hello  *");
        System.out.println("***********");
    }
}

现在,请考虑以下代码段:

Now, consider the following snippet:

Greeter greeter = GreeterFactory.getRandomGreeter();
greeter.greetMe();

getRandomGreeter()方法随机返回 Greeter 对象。它可能返回 Greeter 的对象,或其任何子类,如 FancyGreeter GraphicalGreeter 或任何其他。 getRandomGreeter()将使用 new 创建对象,或者动态加载类文件并使用反射创建对象(I认为可以通过反思)或任何其他可能的方式。所有这些 Greeter 的方法都可以在子类中重写,也可以不重写。因此编译器无法知道是否覆盖了特定方法(是否重载)。对?此外,维基百科在虚拟功能上说:

The getRandomGreeter() method returns a random Greeter object. It may either return an object of Greeter, or any of its subclasses, like FancyGreeter or GraphicalGreeter or any other one. The getRandomGreeter() will create the objects either using new or dynamically load the class file and create object using reflection(I think it is possible with reflection) or any other way that is possible. All of these methods of Greeter may or may not be overriden in subclasses. So the compiler has no way to know whether a particular method(overloaded or not) is overriden. Right? Also, wikipedia says on Virtual functions:


在Java中,所有非静态方法默认为虚函数。
只有标记为关键字final的方法,不能被覆盖,
以及未继承的私有方法,都是非虚拟的。

In Java, all non-static methods are by default "virtual functions". Only methods marked with the keyword final, which cannot be overridden, along with private methods, which are not inherited, are non-virtual.

因为,虚拟函数在运行时使用动态方法调度解析,并且由于所有非私有,非最终方法都是虚拟的(无论是否过载),因此必须在运行时解析它们。对吗?

Since, virtual functions are resolved at run-time using dynamic method dispatch, and since all non private, non final methods are virtual(whether overloaded or not), they must be resolved at run-time. Right?

那么,如何在编译时解决重载?或者,有什么我误解,或者我错过了吗?

Then, How can overloading still be resolved at compile-time? Or, is there anything that I misunderstood, or am I missing?

推荐答案

重载的方法仍然可以被覆盖,如果这是什么你问。

Overloaded methods can still be overridden, if that is what you ask.

重载方法就像不同的系列一样,即使它们共享同一个名称。编译器静态选择给定签名的一个系列,然后在运行时将其分派给类层次结构中最具体的方法。

Overloaded methods are like different families, even though they share the same name. The compiler statically chooses one family given the signature, and then at run time it is dispatched to the most specific method in the class hierarchy.

即执行方法分派分两步:

That is, method dispatching is performed in two steps:


  • 第一个是在编译时完成的,静态信息可用,编译器将发出调用,以获得与调用该方法的对象的声明类型中的重载方法列表中的当前方法参数最匹配的签名。

  • 第二步是在运行时执行的,给定应该调用的方法签名(前一步,记得吗?),JVM会将它调度到实际类型的接收器对象中最具体的重写版本。

  • The first one is done at compile time with the static information available, the compiler will emit a call for the signature that matches best your current method parameters among the list of overloaded methods in the declared type of the object the method is invoked upon.
  • The second step is performed at run time, given the method signature that should be called (previous step, remember?), the JVM will dispatch it to the most concrete overridden version in the actual type of receiver object.

如果方法参数类型根本不是协变的,那么重载相当于在编译时损坏方法名称;因为它们实际上是不同的方法,JVM永远不会根据接收器的类型交替地发送它们。

If the method arguments types are not covariant at all, overloading is equivalent to having methods names mangled at compile time; because they are effectively different methods, the JVM won't never ever dispatch them interchangeably depending on the type of the receiver.

这篇关于重载是编译时多态。真?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆