详细说明:方法重载是静态/编译时绑定,但不是多态性。将静态绑定与多态性相关联是不是正确?
Posted
技术标签:
【中文标题】详细说明:方法重载是静态/编译时绑定,但不是多态性。将静态绑定与多态性相关联是不是正确?【英文标题】:Elaboration: Method overloading is a static/compile-time binding but not polymorphism. Is it correct to correlate static binding with polymorphism?详细说明:方法重载是静态/编译时绑定,但不是多态性。将静态绑定与多态性相关联是否正确? 【发布时间】:2020-01-04 04:07:53 【问题描述】:在我提出问题之前,让我解释一下我的理解和看法。
仅通过覆盖我们无法实现多态性,除非有向上转换。由于它只能在运行时看到,人们可能将其命名为运行时多态。 (我不反对将多态性称为运行时多态性) 我反对将方法重载称为编译时多态或 多态性。我同意方法重载是静态绑定(编译时绑定),但我看不到多态性。
根据javadoc,只有polymorphism。没有编译时或运行时多态性。
根据 javadoc 在名为Defining Methods 的部分中,它解释了方法的重载。但是编译时多态并没有什么。
据我说:
如果将多态性归入运行时多态性的范畴,那么当你改变你的JDK版本时,你只能看到“编译时多态性”:
如果您从较高的 JDK 版本切换到较低的版本,您将开始看到编译错误。相同的代码在编译时表现不同,例如:lambda 表达式、菱形运算符、switch case 中的字符串、泛型等。
让我阐述一下我的观点,我对运行时多态性和编译时多态性如何出现在博客/教程中的预测:
对话1
开发人员 1:嘿,我今天读到了多态性。如果对接口进行编码,则可以实现多态性。编写代码不是与类紧密耦合,而是通过松耦合将其写入接口,调用超类方法或接口方法实际上会根据传递的实例调用子类的方法。
开发者 2:对不起,我没听明白。
开发者 1:在运行时很简单,您将传递哪个对象实例,然后执行该实例方法。
开发者 2: 哦! 运行时间。我明白了。
开发人员 1: 是相同的代码,但在运行时传递的实例不同。
开发者 2:**运行时间!好的,我知道了。
对话2
开发者 2:嘿,昨天我遇到了开发者 1,他正在讲述一些运行时多态性。通过覆盖子类中的方法,我们可以实现它。
开发者 3: 通过重写方法实现运行时多态性?那么什么是超载呢?编译时多态?
开发者 2:您如何将重载称为编译时多态性?
开发者 3: 因为它只在编译时决定。
开发者 2: 静默!
多态和接口编码最好的例子是java.sql:
java.sql.Connection conn = DriverManager.getConnection(DB_URL,USER,PASS);
java.sql.Statement stmt = conn.createStatement();
java.sql.ResultSet rs = stmt.executeQuery(sql);
根据注册的驱动程序,同一段代码的行为会有所不同。这意味着,如果我们注册 mysql 驱动程序,由于多态性,这段代码会执行 mysql 实例的方法。 IE。它执行被覆盖的方法。如果您注册了Oracle驱动程序,它适用于Oracle,等等。
在上面我们发现相同的代码表现不同。
现在任何人都可以向我展示在编译时表现不同的相同代码。或者换句话说,告诉我add(3,4)
在编译期间绑定到不同方法(其他签名方法)的方法?
According to javadoc,
Java 编程语言支持重载方法,Java 可以区分具有不同方法签名的方法。
该方法将根据匹配的签名执行。方法同名不代表多态,因为调用方法的签名不同:
问题1:如果您不更改调用方法签名,它会调用与签名匹配的方法不同的方法吗?在任何情况下它的行为都会有所不同吗?
让我们看看方法重载:
public void add(int a, int b)
System.out.println(a+b);
public void add(int a, int b, int c)
System.out.println(a+b+c);
public static void main(String[] args)
add(3,4);
add(3,4,5);
问题 1: 如果方法重载是多态,那么在上面的代码块中哪一段代码的行为不同?这里的多态性在哪里?
问题2:方法调用add(3,4);
在什么场景下显示多态,除非修改为add(3,4,5)
?
编辑@FutureVisitor,因为该线程没有找到支持将方法重载作为一种多态性的答案(即使在提出一个月的问题之后),没有任何理由接受支持方法重载不是多态性的答案,如果我的方法重载论点中的任何答案点问题不是多态性,将被接受并支持他们的观点。
【问题讨论】:
我认为您的困惑来自这样一个事实,即 java 文档对多态性的定义与计算机科学中对多态性的定义略有不同。 java 文档似乎只将运行时多态称为“多态”,但计算机科学的定义更为笼统。 在我看来 JavDoc 是正确的。 @PraveenKumarLalasangi “编译时”和“运行时”已经是特例了,CS 玩的总是最一般的。 Java 世界观只是众多可能的世界观之一(注意,我认为 Java 有一个非常好的世界观)。 把很多东西关联起来是人类的普遍行为。这就是它导航到教科书、博客等的原因。但是在编写故事时,开发人员不应该犯任何错误,否则它将成为 QA 团队的食物。 Javadoc 避免过度解释以避免混淆。否则它可能会提到方法重载是否是多态性。 【参考方案1】:在 Java 世界中,多态是指类之间的多态。 IE。与共同的父母一起引用可能的多个子类。在 Java 中,方法之间没有多态性。
void add(int a, int b)
和 void add(int a, int b, int c)
在 Java 语法中是完全不同的方法。不应该是这样 - 例如,在 C++ 中,您可以将它们cast 相互转换 - 但在 Java 中却是这样。
这里要理解的关键概念是method signature。方法签名在一种语言中定义了标识单个方法的内容。 (例如,除了void add(int a, int b);
,您根本不能声明int add(int a, int b);
方法——返回值不是Java 中方法签名的一部分,因此编译器会将其解释为方法重新定义。)
【讨论】:
我不确定,我回答了你想知道的一切。随时向我提出扩展建议。 您通过添加点“具有不同签名的方法是两种不同的方法”为我的论点增加了价值。【参考方案2】:人们说
-
重写是运行时多态性和
重载是编译时多态性。
两者都错了。 只有覆盖不是多态性。但是重写有助于实现多态性。如果没有向上转型,就无法实现多态性。
重载是一个概念,其中方法名称和参数签名用于将方法调用绑定到方法主体,并且只能在编译时预测。但这与多态性无关。在方法重载的情况下,没有行为变化。无论是今天编译还是一年后编译,只有在更改调用方法签名时才能发现行为变化,即,只有将代码修改为 add(3,4);
为 add(3,4,5);
,因此 方法重载不是多态性.
【讨论】:
以上是关于详细说明:方法重载是静态/编译时绑定,但不是多态性。将静态绑定与多态性相关联是不是正确?的主要内容,如果未能解决你的问题,请参考以下文章