Как вызвать реализацию интерфейса метода по умолчанию в переопределяющей реализации?
Предположим, у меня есть следующий код:
interface HumanoidForm {
default HumanoidForm reproduce() {
<appropriate code for humanoid form reproduction>
}
}
class Android extends Machine implements HumanoidForm {
public HumanoidForm reproduce() {
<appropriate code for android reproduction> // how to use HumanoidForm's default implementation here?
}
}
Теперь предположим, что "соответствующий код для воспроизведения андроида" лучше всего описывается с использованием "соответствующего кода для воспроизведения гуманоидной формы" в качестве подпрограммы. Как я могу получить доступ к "соответствующему коду для гуманоидной формы" из "соответствующего кода для воспроизведения Android"? Я могу придумать три способа, но ни один из них не работает:
- Простой вызов repce() вызывает реализацию с переопределением.
- Запись ((HumanoidForm) this).reproduce() по-прежнему вызывает переопределяющую реализацию.
- Подражая повторному использованию реализаций методов в суперклассах путем переопределения методов, можно подумать о написании super.reproduce(). Тем не менее, это относится к реализации воспроизведения машины, которая может даже не существовать.
Таким образом, кажется, нет способа повторно использовать код в методе по умолчанию для переопределения. Это действительно так?
4 ответа
На самом деле, вы можете свободно выбирать существующую реализацию. Позвольте мне дать вам сценарий, немного более сложный, чем ваш. Что еще хуже, все A
,B
& C
имеет такую же сигнатуру метода.
interface A {
default void doWork() {
System.out.println("Default implementation From A");
}
}
interface B{
default void doWork() {
System.out.println("Default implementation From B");
}
}
class C{
void doWork(){
System.out.println("Default implementation From C");
}
}
Теперь я создаю подкласс для C, который реализует A & B:
class Tester extends C implements A, B
{
@Override public void doWork(){
A.super.doWork(); //Invoke A's implementation
B.super.doWork(); //Invoke B's implementation
super.doWork(); //Invoke C's implementation
}
}
Выход будет:
Default implementation From A
Default implementation From B
Default implementation From C
когда вы бежите:
new Tester().doWork();
Взгляните на это: https://blog.idrsolutions.com/2015/01/java-8-default-methods-explained-5-minutes/
В частности, в разделе, где говорится:"Если мы хотим специально вызвать один из методов sayHi () в InterfaceA или InterfaceB, мы также можем сделать следующее:"
public class MyClass implements InterfaceA, InterfaceB {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
}
@Override
public void saySomething() {
System.out.println("Hello World");
}
@Override
public void sayHi() {
InterfaceA.super.sayHi();
}
}
interface InterfaceA {
public void saySomething();
default public void sayHi() {
System.out.println("Hi from InterfaceA");
}
}
interface InterfaceB {
default public void sayHi() {
System.out.println("Hi from InterfaceB");
}
}
Таким образом, кажется, нет способа повторно использовать код в методе по умолчанию для переопределения. Это действительно так?
Нет, вы можете повторно использовать код. Вы можете легко проверить это, и вы увидите, что следующий код работает:
public class Test implements HumanoidForm
{
public static void main(String[] args)
{
new Test().reproduce();
}
@Override
public void reproduce(){
HumanoidForm.super.reproduce(); //Invoking default method
System.out.println("From implementing class");
}
}
interface HumanoidForm {
default void reproduce() {
System.out.println("From default interface");
}
}
ВЫХОД:
From default interface
From implementing class