选择正确的调用方法

时间:2011-04-28 17:54:28

标签: java methods

5 个答案:

答案 0 :(得分:3)

该方法的动态绑定在运行时在具有相同签名的不同实现之间应用,但是当编译器查看签名时,静态地确定所有可能方法的集合。由于您将p声明为Parent类,因此在运行时它将查找Parent类中存在的方法,如果存在更具体的实现(因为子类) ,就像在你的例子中),然后它将被选择为祖先。

由于您的方法没有覆盖任何内容,因此在编译时它将选择一个不同的签名(Object的签名)并忽略它。由于属性p的类型,它在运行时似乎不是匹配的可能性。

答案 1 :(得分:0)

您上传了ChildParent

Parent p = new Child();

当您调用p.doIt("test");时,您将获得Child行为的唯一方法是通过重写方法。

由于您已将Child中的方法更改为doIt(String s),因此不再覆盖Parent中的任何内容,因此doIt(Object o)中会调用Parent

答案 2 :(得分:0)

您的答案实际上非常简单:您对方法的更改破坏了对继承的使用。

Parent只有一个doIt方法,它接受一个Object参数。当您在父级上调用doIt(“test”)时,它会查看是否在子级中覆盖它。由于未在子节点中覆盖doIt(Object s),因此使用父方法。即使你传递一个String,仍会调用父方法,因为doIt(Object s)与doIt(String s)不同。

简单地说,当您更改签名时,您没有覆盖该方法,而是超载它。

答案 3 :(得分:0)

要调用的方法签名是在编译时确定的,因此p.doIt(“test”)将在运行时调用相应类的doIt(Object o)方法。 doIt(String s)甚至没有看过。想象一下,当编写Poly makeItHappen时,Child.java不存在 - 您还必须将Child构造函数抽象为另一个类中的工厂方法以使其编译。您可以重新实现工厂方法和Child.java,而无需重新编译Poly.java。这允许您编程到基类提供的接口和相对有效的函数调用。您的Poly makeItHappen只需要知道doIt(Object o)存在。

如果您考虑通过虚函数表实现继承的可能性,那么doIt(String s)和doIt(Object o)具有不同的表条目。 Parent只有doIt(Object o)的条目。 Child既有doIt(Object o)的条目,它是与Parent相同的主体,也是doIt(String s)的条目,它是它自己的条目。在编译时,要调用的方法是doIt(Object o)槽中的方法。

答案 4 :(得分:0)

嗯,试图解决'为什么'运行时没有播放隐藏和寻找与整个类定义寻找'更好'匹配方法比编译器要求的方法,将举例。显然这个API首先是可怕的,但是你可以想象使用很长的方法签名会不会意外地发生这种情况。

/**
* Vendor API you program to
*/
public class IPv4Manager {
  public void terminateSocket(Object obj) {
    //terminate IPv4 socket
  }
}

/**
* Vendor class that's injected at runtime that you have no knowledge of 
* and do not compile against.
*/
public class IPv4And6Manager extends IPv4Manager {

  public void terminateSocket(Byte[] packet) {
    //terminate IPv6 socket
  }

}

/**
*Your user code
*/
public void terminateIPv4Socket(Byte[] packet) {
  IPv4Manager manager = managerFactory.getV4Manager(); //returns you an instance of 4And6Manager
  manager.terminateSocket(packet);
}

你是否真的希望运行时试图超越你并调用比编译器要求的“更好”的方法?