Java接口:继承、覆盖和重载方法

9
在《Java™编程语言 第四版》一书中,作者Ken Arnold、James Gosling和David Holmes提到: 段落:(4.3.2) “同样地,如果一个接口继承了多个具有相同签名的方法,或者一个类实现了包含具有相同签名的方法的不同接口,则只有一个这样的方法。该方法的实现最终由实现接口的类定义,并且在那里没有歧义。如果这些方法具有相同的签名但返回类型不同,则其中一个返回类型必须是所有其他返回类型的子类型,否则会发生编译时错误。实现必须定义一个返回该通用子类型的方法。” 有人能给我一些代码示例来证明上述段落的观点吗? 我尝试编写代码并测试所述内容,但我得到了编译时错误,因为子接口隐藏了基础接口方法,因此只能实现子接口方法。
谢谢。 -Arun

1
发帖时请附上您的代码和编译器错误信息,至少让我们有些东西可以(a)重现问题;(b)从那里开始。 - corlettk
大家好,非常抱歉 - 我试图使用j2sdk1.4.2_08测试上面提到的段落中提到的内容 - 我没有意识到这本书是为JDK1.5编写的。这意味着如果您使用JDK1.4编译“Daniel Schneller”使用的代码片段,您将获得“ImplementationOfAandB.java:17:methodB()在ImplementationOfAandB中不能实现InterfaceA中的methodB();尝试使用不兼容的返回类型”编译错误,而使用JDK1.5则可以正常运行。 - akjain
5个回答

8
interface A {
    void method();
    Object returnMethod();
}
interface B {
    void method();
    B returnMethod();
}

class Impl implements A,B 
{
    void method() { }
    B returnMethod() { }
}

如您所见,Impl.method() 实现了 A.method()B.method(),而 Impl.returnMethod() 返回一个 B,它是 Object 的子类,因此也满足了 A.returnMethod() 的约定。如果后者需要一个返回类型,而该类型不是 B.returnMethod() 返回类型的父类,则会出现编译错误,因为在 Impl 中不存在这样的实现。


那是C#吗?这个问题是关于Java的。 - Joachim Sauer
我认为语言并不重要 ;) - Norbert Hartl
3
不,Impl必须实现更具体的返回类型才能满足两个接口的要求。 - Michael Borgwardt

2
在下面的两个接口中,methodA()以参数(无)和返回类型(int)完全相同的方式定义。底部的实现类定义了一个具有这个确切签名的单个方法。因为它符合两个接口的规定,所以你不会遇到任何问题 - 通过InterfaceA或InterfaceB类型的引用进行的任何调用都将分派到此实现。
第二个methodB()InterfaceA中被定义为返回Number的任何子类型(或Number本身)。InterfaceB定义methodB()返回Integer,它是Number的一个子类型。实现类实际上使用Integer实现了该方法,因此符合InterfaceAInterfaceB的契约。这里也没有问题。
然而,注释掉的methodB()实现为返回Double将不起作用:虽然它会满足InterfaceA的契约,但它会与要求IntegerInterfaceB冲突。
如果InterfaceAInterfaceB还为methodC()(在示例中已注释掉)指定了(不同的)契约,则会产生矛盾并创建编译器错误。在Java中不允许实现两个签名(仅返回类型不同)。
以上规则也适用于向方法添加任何参数。为简单起见,我在示例中省略了此内容。
public interface InterfaceA {
    public int methodA();
    public Number methodB();
    // public int methodC(); // conflicting return type
}

public interface InterfaceB {
    public int methodA();
    public Integer methodB();
    // public String methodC(); // conflicting return type
}

public class ImplementationOfAandB implements InterfaceA, InterfaceB {
    public int methodA() {
        return 0;
    }
    public Integer methodB() {
        return null;
    }
    // This would NOT work:
    // public Double methodB() {
    //     return null;
    // }
}

大家好,非常抱歉 - 我试图使用j2sdk1.4.2_08测试上面提到的段落中提到的内容 - 我没有意识到这本书是为JDK1.5编写的。这意味着,如果您使用JDK1.4编译“Daniel Schneller”使用的代码片段,您将获得一个“ImplementationOfAandB.java:17: methodB() in ImplementationOfAandB cannot implement methodB() in InterfaceA; attempting to use incompatible return type”编译错误,而使用JDK1.5则可以正常运行。 - akjain

1
interface A
{
   void foo();
   //int bar(); <-- conflicts with B.bar() because of different return type
}

interface B
{
   void foo();
   //double bar(); <-- conflicts with A.bar() because of different return type
}

class C implements A, B
{
   void foo() // this implements A.foo() AND B.foo()
   {
      ...
   }
}

1

您是指这个吗?

interface A {
    Object get();
}
interface B {
    Number get();
}

abstract class MyClass implements A, B {
    // Try to override A.get, but cause a compile error.
    public Object get() { return null; }
}

MyClass中的这种方法是由javac自动生成的合成桥接方法。您必须实现一个返回类型与所有已实现/覆盖的方法兼容的单个方法(在本例中为Number/Integer/Double/等)。


1
/**
 * This is what you have
 */
interface IXR {
        //bla-bla-bla
}

class CXR implements IXR {
        //concrete implementation of bla-bla-bla
}

interface IX {
        public IXR f();
} 

interface IYR {
        //some other bla-bla-bla
}

class CYR implements IYR {
        //concrete implementation of the some other bla-bla-bla
} 

interface IY {
        public IYR f();
}






/**
 * This is what you need to add
 */ 
interface IZR extends IXR, IYR {
        //EMPTY INTERFACE
}

class CZXR extends CXR implements IZR {
        //EMPTY CLASS
} 

class CZYR extends CYR implements IZR {
        //EMPTY CLASS
}

class CZ implements IX, IY
{
        public static boolean someCondition = true;

        public IXR implementationOf_X_f()
        {
                System.out.println("CXR");
                return new CZXR();
        }

        public IYR implementationOf_Y_f()
        {
                System.out.println("CYR");
                return new CZYR();
        }

        public IZR f() {
                if (someCondition) {
                        return (IZR) implementationOf_X_f();
                } else {
                        return (IZR) implementationOf_Y_f();
                }
        }

}






/**
 * This is the usage of the required class
 */
class program 
{ 
        public static void main(String[] x) {
                CZ o = new CZ();
                IZR r = o.f();
                if (CZ.someCondition) {
                        CXR xr = (CXR) r;
                        //bla-bla-bla
                } else {
                        CYR yr = (CYR) r;
                        //bla-bla-bla
                }
        }
} /**
 * This is what you have
 */
interface IXR {
        //bla-bla-bla
}

class CXR implements IXR {
        //concrete implementation of bla-bla-bla
}

interface IX {
        public IXR f();
} 

interface IYR {
        //some other bla-bla-bla
}

class CYR implements IYR {
        //concrete implementation of the some other bla-bla-bla
} 

interface IY {
        public IYR f();
}






/**
 * This is what you need to add
 */ 
interface IZR extends IXR, IYR {
        //EMPTY INTERFACE
}

class CZXR extends CXR implements IZR {
        //EMPTY CLASS
} 

class CZYR extends CYR implements IZR {
        //EMPTY CLASS
}

class CZ implements IX, IY
{
        public static boolean someCondition = true;

        public IXR implementationOf_X_f()
        {
                System.out.println("CXR");
                return new CZXR();
        }

        public IYR implementationOf_Y_f()
        {
                System.out.println("CYR");
                return new CZYR();
        }

        public IZR f() {
                if (someCondition) {
                        return (IZR) implementationOf_X_f();
                } else {
                        return (IZR) implementationOf_Y_f();
                }
        }

}






/**
 * This is the usage of the required class
 */
class program 
{ 
        public static void main(String[] x) {
                CZ o = new CZ();
                IZR r = o.f();
                if (CZ.someCondition) {
                        CXR xr = (CXR) r;
                        //bla-bla-bla
                } else {
                        CYR yr = (CYR) r;
                        //bla-bla-bla
                }
        }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接