Есть ли способ перегрузить абстрактный метод в функциональном интерфейсе? - PullRequest
1 голос
/ 30 мая 2019

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

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

Я хотел бы иметь возможность написать что-то вроде следующего кода:

Ball b = () -> System.out.println("You hit it!");
Ball ba = (boolean miss) -> System.out.println(miss);

b.hit();
b.hit(false);
ba.hit();
ba.hit(false);

Желаемый результат будет:

You hit it!
default false
default hit
false

Рассмотрим следующее (некомпилируемый) код (в основном скопированный из связанного вопроса):

@FunctionalInterface
public interface Ball
{
    void hit();
    void hit(boolean miss);
    default void hit(){
        System.out.println("default hit");
    }
    default void hit(boolean miss){
        System.out.println("default" + miss);
    }

}

Я ищу альтернативу этому коду, который компилируется.

Ответы [ 3 ]

1 голос
/ 30 мая 2019

Вы могли бы сделать что-то вроде этого.Но вам нужно было бы правильно назвать свои переменные, чтобы отслеживать как arg, так и consumer, который их принимает.

@FunctionalInterface
interface Ball<T> {
   void hit();

   static <T> Ball<T> withArg(T arg, Consumer<T> com) {
      return () -> com.accept(arg);
   }
}

public class Demo {
   public static void main(String[] args) {
      Ball<Boolean> b = () -> System.out.println("You Hit it!");
      b.hit();
      Ball<Boolean> ba = Ball.withArg(false, a -> System.out.println(a));
      Ball<Boolean> bb = Ball.withArg(true, a -> System.out.println(a));
      ba.hit();
      bb.hit();
   }
}
0 голосов
/ 31 мая 2019

Вы можете заключить интерфейс в класс и затем передать вызовы методов внутренним интерфейсам.

Пример кода:

public class Test{
    public static void main(String... args) throws Exception{
        Ball b = new Ball(() -> System.out.println("You hit it!"));
        Ball ba = new Ball((boolean miss) -> System.out.println(miss));

        b.hit();
        b.hit(false);
        ba.hit();
        ba.hit(false);
    }

    static public class Ball{
        final Hit a;
        final HitBoolean b;

        public Ball(Hit a){
            this.a = a;
            b = (miss) -> System.out.println("default " + miss);
        }

        public Ball(HitBoolean b){
            this.b = b;
            a = () -> System.out.println("default hit");
        }

        public void hit(){
            a.hit();
        }

        public void hit(boolean miss){
            b.hit(miss);
        }
    }

    public interface Hit{
        void hit();
    }

    public interface HitBoolean{
        void hit(boolean miss);
    }
}

Вывод программы:

You hit it!
default false
default hit
false
0 голосов
/ 30 мая 2019

Первое, что касается функционального интерфейса, это то, что он может иметь только один абстрактный метод. В этом случае вы даже не можете думать о втором методе (пусть это тоже будет абстрактный метод).у вас может быть любое количество методов по умолчанию.

Таким образом, ответ на 100% невозможен, и ваш код, приведенный выше, получит ошибку компиляции, поскольку вы сохранили аннотацию @FunctionalInterface, которая строго запрещает хранить более одного абстрактного метода.В соответствии с вашим кодом

@FunctionalInterface
public interface MyInter {
    public abstract void fly();

    public abstract void fly(int a);

    default void fly() {}          \\line1
    default void fly(int g) {   }   \\line2
}

строки 1 и 2 приведут к ошибке времени компиляции, так как java видит их по имени метода, и типы аргументов одинаковы, они никогда не будут беспокоиться о типе возвращаемого значения или по умолчанию или т. Д.(основное правило перегрузки).

больше, если удалить строки 1 и 2, то и код выдаст ошибку, потому что @functionalinterface выдаст ошибку компиляции с указанием недопустимой аннотации @FunctionalInterface;MyInter не является функциональным интерфейсом .

Надеюсь, это ответит на ваш вопрос ...

...