Расширение интерфейса Generi c для универсальной проверки c - PullRequest
0 голосов
/ 01 августа 2020

Я играл с шаблоном проверки из этого сообщения в блоге. Все работает, как ожидалось, но я не могу добавить дженерики. А именно,

public interface Validator extends Function<User, ValidationResult> {
    static Validator validate(Predicate<User> tester, String error) {
        return user -> 
            tester.test(user) ? ValidationResult.valid() : 
                    ValidationResult.invalid(error);
    }
}

Однако, когда я пытаюсь сделать интерфейс Validator generi c

public interface Validator<T> extends Function<T, ValidationResult> {
    static Validator validate(Predicate<T> tester, String error) {
        return subject ->
                tester.test(subject) ? ValidationResult.valid() :
                        ValidationResult.invalid(error);
    }
}

, я получаю ошибку компиляции:

Validatior. На это нельзя ссылаться из контекста stati c.

введите описание изображения здесь

Не понимаю почему. Что я делаю не так?

Ответы [ 2 ]

1 голос
/ 01 августа 2020

«… Не понимаю почему. Что я делаю не так? … «

Что вы делаете неправильно, это ссылаетесь на параметр типа в контексте stati c. JLS говорит, что это недопустимо

Ссылка на параметр типа обобщенного объекта является ошибкой времени компиляции. c класс C в любом из следующих :

  • объявление статического c члена C ( §8.3.1.1 , §8.4.3.2 , §8.5.1 ).

  • объявление члена stati c любого объявления типа, вложенного в C.

  • stati c инициализатор C ( §8.7 ), или

  • stati c инициализатор любого объявления класса, вложенного в C.

Один из способов компиляции кода - измените его на это…

public interface Validator<T> extends Function<T, ValidationResult> {
    
    default Validator validate(Predicate<T> tester, String error) {
        return user -> 
            tester.test((T)user) ? ValidationResult.valid() : 
                    ValidationResult.invalid(error);
    }
}
0 голосов
/ 01 августа 2020

Мой первый ответ предполагает, что вам не нужно ничего, кроме исходного кода, который вы отправили для компиляции; с наименьшим количеством изменений. Таким образом, этот ответ касается только этого предположения.

Это другой ответ, потому что он делает другое предположение; и требует более одного изменения кода.

Допущение : Вы абсолютно должны иметь статус c method?

Вы можете получить это с помощью следующих рефакторов:

  • Добавьте интерфейс Validatible ...

      public interface Validatible{ 
    
          boolean isValid();
    
      }
    
  • Марка User a Validatiable

      public class User implements Validatible{
          ...
    
          @Override
          public boolean isValid(){
              ...
          }
          ... 
      }
    
  • Упростить Validator

      public interface Validator {
    
          ValidationResult validate(Validatible input);
      }
    
  • Переместите must-have static метод в служебный / вспомогательный класс…

      public class DeduperAnswer {
    
          static Validator validate(Predicate<Validatible> tester, String error) {
              return user -> 
                  tester.test(user) ? ValidationResult.valid() : 
                          ValidationResult.invalid(error);
          }
          ...
      }
    

Затем вы можете вызвать DeduperAnswer.validate() , как я в этой демонстрации

    Validator butWhatThen = DeduperAnswer.validate((user) -> { return user.isValid(); }, "not valid");

Но, как я спросил в комментариях, после того, как вы вернетесь, Validator из вызова метода static, Что вы собираетесь с ним делать тогда?

Я сделал предположения, которые сделал, потому что не на 100% ясно, каков ваш конкретный вариант использования. Было бы очень полезно, если бы вы этим поделились.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...