动态绑定

时间:2012-09-26 16:16:21

标签: java

如果类实现了接口并且具有toString()方法 我们将子引用存储到父变量中,或者只是完成动态绑定 那么为什么编译器没有检查接口中的toString()方法,因为它是一个规则 函数唯一性的动态绑定将在父级中检查

例如

interface my {
    void show();
}

class child implements my {
    public void show() {
        System.out.println("working");
    }

    public String toString() {
        return "hello";
    }

    public static void main(String... s) {
        my m = new child();

        m.show();

        String s = m.toString();
        System.out.println(s);
    }
}

我们知道,每当动态绑定完成时,除非已覆盖上述方法,否则无法执行子个人方法 那么为什么上面的函数toString()得到了编译并给出了输出?

4 个答案:

答案 0 :(得分:3)

听起来你在问这个问题:

在我的示例代码中,局部变量m的类型为my。界面my只声明了一个方法show(),那为什么我可以致电m.toString()

在Sun(现在的Oracle)Java tutorial on inheritance中解释了这一点:

  
    

类可以从派生自类的类派生的类派生,依此类推,而最终派生自最顶层的类。这样的类据说是来自继承链中的所有类都延伸回Object。

  

The Object class声明了一个默认的toString()方法(以及其他一些基本方法),因此您可以在任何对象上调用toString()


<强>更新

由于Java 中的所有类实例必须继承自Object,因此将接口用作类型的实际语义更像是:

public static void main(String... s) {
    // This won't actually compile
    (? extends Object implements my) m = new child(); 

    m.show();

    String s = m.toString();
    System.out.println(s);
}

换句话说,当您声明m类型为my时,您实际上是说m是实现接口Object的某些my 。由于Object声明了toString()方法,即使m.toString()界面中不存在toString(),您也可以致电my

Java是专门设计的,在类层次结构的顶部有Object,所以你无法让编译器抱怨在任何对象的任何实例上调用toString()hashCode()equals()等也是如此。

答案 1 :(得分:1)

我认为你的问题将通过已经给出的两个答案来解决。我只是想指出一些关于你的陈述的事情: -

  • if a class implements an interface and have a toString() method

您定义的任何类都有toString()方法..虽然看起来不太明显,但是当您打印类的实例时,它是toString()类的Object方法调用它。(Object类是您定义的所有其他类的超类。)因此,Object类中定义的任何方法都可以从任何其他class object访问。

您可以覆盖此方法以根据需要打印您的实例。但是,如果没有覆盖,您将获得对象的hashcode ..(例如: - classname@12343。现在由于这个toString()方法适用于所有类,编译器不需要在任何interface中检查它。它知道toString()方法是Object的一部分} class是所有类的super class ..

  • we store the child reference into parent variable

虽然你的理解是正确的,但让我重新构思这句话,使其更有意义: - We Store the reference to child class object in the parent class reference variable

  • function uniqueness will be check in parent

我真的无法理解,这句话是什么意思..但据我所知,你是这么说的 - “当child class上调用parent class reference的方法时,然后编译器将首先检查该方法是否在parent class中定义,然后只能调用该方法..

*编辑* : -

根据Java Language Specification,第9.2节: -

  

如果接口没有直接的超级接口,那么接口   隐式声明带有签名的公共抽象成员方法m   s,返回类型r,以及对应于每个公共的throws子句t   具有签名s的实例方法m,返回类型r和throws子句t   在Object中声明,除非具有相同签名的方法相同   返回类型,并且显式声明了兼容的throws子句   界面。

     

如果接口明确声明了这样的,那么这是一个编译时错误   方法m在m被声明为Object的最终的情况下。

     

如果接口声明了,那么这是一个编译时错误   具有覆盖等效(§8.4.2)的签名的方法   Object的公共方法,但具有不同的返回类型或   不兼容的投掷条款。

答案 2 :(得分:0)

所有对象都延伸Objectpublic String toString()中定义了Object,因此所有对象都有toString()方法。

答案 3 :(得分:0)

如果你问我认为你在问什么,那是因为Java中的每个非原语(原语是intlong等;但不是String)类型ObjectObject有方法toString()hashCode()equals(),这意味着任何非基元也都有这些方法。

但是,这些方法通常过于通用,无法用于特定的类,这就是我们在需要时重载它们的原因。