【问题标题】:Java - Interface MethodsJava - 接口方法
【发布时间】:2012-05-22 03:16:28
【问题描述】:

只是在玩接口,我有一个我无法真正理解的问题。

以下代码无法运行,这是我所期望的行为,因为接口方法要求该方法适用于任何对象,并且实现的方法已将签名更改为仅允许字符串对象。

interface I {
    public void doSomething(Object x);
}

class MyType implements I {
    public void doSomething(String x) {
        System.out.println(x);
    }
}

但是,使用下面的代码块,我很震惊地发现它确实有效。 我认为它不起作用,因为我们期望返回一个对象,而实现的方法只会返回一个字符串对象。为什么会这样,这里传递参数和返回类型这两个原则有什么区别?

interface I {
    public Object doSomething(String x);
}

class MyType implements I {
    public String doSomething(String x) {
        System.out.println(x);
        return(x); 
    }
}

【问题讨论】:

    标签: java methods interface implements


    【解决方案1】:
    public Object doSomething(String x);
    

    必须返回一些东西。事实上,任何东西,只要它是某种类型的对象。所以如果你实现

    public String doSomething(String x) {stuff}
    

    这很好,因为它实际上返回了一个对象。它将返回的对象总是一个字符串这一事实没什么大不了的。

    第一个示例不起作用的原因是,仅接受字符串比接受任何对象更具限制性。但是只返回字符串就可以了。

    打个比方,假设您签订了粉刷建筑物的合同,并且您将雇用一些员工来帮助您。合同要求您雇用任何适用的油漆工,无论他们有多高,但没有指定使用什么颜色的油漆。如果您只雇用超过 6 英尺高的画家(这是输入,只接受 String 而不是所有 Object),您将违反合同。但是选择只用蓝色油漆(只返回字符串)就可以了,因为合同没有指定颜色,只是你必须给建筑物涂漆。

    【讨论】:

      【解决方案2】:

      之所以有效,是因为 StringObject

      【讨论】:

      • 嗯,这不是真正的答案。他的第一个例子有同样的“演员表”。 maress 解释了它第二次起作用的原因
      • 他的第一个例子中没有演员表。该接口声明了一个将对象作为参数的方法。拥有一个接受字符串的方法与接受一个对象不同。你能把一个整数传递给他的字符串方法吗,就像你可以传递一个对象一样?
      • 这更像是一个答案,但还不够:p
      【解决方案3】:

      这与 Java SE 5.0 中引入的协变返回类型有关。
      更多详情请见http://docs.oracle.com/javase/tutorial/java/javaOO/returnvalue.html

      【讨论】:

        【解决方案4】:

        来自java语言规范:

        如果返回类型是引用类型,则返回类型可能会因相互覆盖的方法而异。 return-type-substitutability 的概念支持协变返回,即将返回类型特化为子类型。

        也就是说,它就像你做的那样工作,但是如果接口中的返回类型是String,而实现类中的返回类型是Object,它将无法工作。

        【讨论】:

          【解决方案5】:

          这种行为背后的原理称为covariant return type。在这种特殊情况下,覆盖类型可能会“缩小”最初声明的参数类型。

          这意味着由于StringObject 的子类,Object 可以被String 替换。

          【讨论】:

            【解决方案6】:

            第一个示例不起作用而第二个示例起作用的原因是因为函数原型仅由名称和所有参数定义,而不是返回类型。在第一个示例中,存在差异,因此编译器认为它们是两个不同的函数。

            在第二个例子中,实现的函数并没有拓宽类型,而是特化了类型(String是Object的特化),所以可以。

            同样,您可以限制已实现方法的可见性,但不能扩大它。

            此外,Java 有泛型,在这种情况下很有用。

            例子:

            interface I<T>
            {
                public void doSomething(T x);
            }
            
            class MyType implements I<String>
            {
                public void doSomething(String x)
                {
                    System.out.println(x);
                }
            }
            

            【讨论】:

              【解决方案7】:

              方法签名不考虑返回类型。 (虽然声明两个具有相同签名但返回类型不同的方法是错误的)。所以:

              void doSomething(Object)
              void doSomething(String)
              

              只是两个方法,没有一个覆盖或实现另一个

              【讨论】:

                【解决方案8】:

                字符串类继承自对象类,所以只有这段代码有效。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2019-02-10
                  • 2014-07-17
                  • 2017-03-26
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2010-12-16
                  相关资源
                  最近更新 更多