Интерфейс Java: методы наследования, переопределения и перегрузки

в "языке программирования Java™, четвертое издание" Кена Арнольда, Джеймса Гослинга, Дэвида Холмса, упоминается, что:

абзац: (4.3.2) "аналогично, если интерфейс наследует несколько методов с одной и той же сигнатурой или если класс реализует разные интерфейсы, содержащие метод с одной и той же сигнатурой, существует только один такой метод. Реализация этого метода в конечном счете определяется классом, реализующим интерфейсы, и здесь нет никакой двусмысленности. Если методы имеют одинаковую сигнатуру, но разные типы возврата, то один из типов возврата должен быть подтипом всех остальных, иначе возникает ошибка времени компиляции. Реализация должна определить метод, который возвращает этот общий подтип."

может ли кто-нибудь дать мне пример кода, который оправдывает пункты выше абзаца ?

Я попытался написать код и проверить, что упоминается, но я получаю Ошибка времени компиляции подинтерфейс скрывает метод базового интерфейса, поэтому может реализовать только метод подинтерфейса.

спасибо заранее. - Арун!--1-->

5 ответов


в следующих двух интерфейсов methodA() одинаково определяется с точки зрения параметров (нет) и возвращаемого типа (int). Класс реализации внизу определяет один метод с этой точной сигнатурой. Поскольку он соответствует обоим интерфейсам, вы не получаете никаких проблем - любые вызовы, сделанные через ссылку типа InterfaceA или InterfaceB, будут отправлены в эту реализацию.

второй methodB() определяется как возвращающий любой подтип Number (или ) в InterfaceA. InterfaceB определяет methodB() в качестве возврата Integer, который является подтипом Number. Класс реализации фактически реализует метод с помощью Integer, в соответствии с договором как InterfaceA и InterfaceB. Здесь тоже нет проблем. Прокомментированный случай methodB() реализуется как возвращение Double однако не будет работать: в то время как он будет удовлетворять контракту InterfaceA, это противоречило бы InterfaceB (который требует Integer).

если InterfaceA и InterfaceB также указывали (разные) контракты для 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;
    // }
}

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()тип возврата, который был бы ошибкой comile, так как такая реализация не может существовать в Impl.


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()
   {
      ...
   }
}

ты это имеешь в виду?:

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/и т. д.).


/**
 * 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
                }
        }
}