扩展泛型接口以进行泛型验证

huangapple go评论82阅读模式
英文:

Extending Generic Interface for generic validation

问题

I have been playing with the validation pattern from this blog post. Everything works out as expected but I am unable to add generics. Namely,

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);
    }
}

However, when I try to make the Validator interface generic

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);
    }
}

I get a compilation error:

Validatior.this cannot be referenced from the static context.

扩展泛型接口以进行泛型验证

I can't understand why. What am I doing wrong?

英文:

I have been playing with the validation pattern from this blog post. Everything works out as expected but I am unable to add generics. Namely,

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

However, when I try to make the Validator interface generic

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

I get a compilation error:

> Validatior.this cannot be referenced from the static context.

扩展泛型接口以进行泛型验证

I can't understand why. What am I doing wrong?

答案1

得分: 1

以下是要翻译的内容:

"我不明白为什么。我做错了什么吗?"

你做错的地方是在静态上下文中引用了类型参数。JLS规范说这是不允许的

在以下情况下引用泛型类C的类型参数都会导致编译时错误

  • C内的任何类型声明的静态成员声明
  • C的静态初始化器 (§8.7),
  • 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);
    }
}
英文:

> „&hellip;I can't understand why. What am I doing wrong?&hellip;“

What you're doing wrong is referring to the type parameter in a static context. The JLS says that's not allowed&hellip;

> It is a compile-time error to refer to a type parameter of a generic class C in any of the following:
>
> - the declaration of a static member of C (§8.3.1.1, §8.4.3.2, §8.5.1).
>
> - the declaration of a static member of any type declaration nested within C.
>
> - a static initializer of C (§8.7), or
>
> - a static initializer of any class declaration nested within C.

One way to make your code compile is to change it to this&hellip;

public interface Validator&lt;T&gt; extends Function&lt;T, ValidationResult&gt; {
    
    default Validator validate(Predicate&lt;T&gt; tester, String error) {
        return user -&gt; 
            tester.test((T)user) ? ValidationResult.valid() : 
                    ValidationResult.invalid(error);
    }
}

答案2

得分: 0

My first answer assumes you want nothing more than for the original code you posted to compile; with the fewest changes made to it. So that answer addresses only that assumption.

这个回答假定您只希望原始代码能够编译,而对其进行的更改最少。因此,这个回答仅仅解决了这个前提。

This is a different answer because it makes a different assumption; and requires more than one code change.

这是一个不同的回答,因为它基于不同的假设,并需要进行多个代码更改。

Assumption: You absolutely must have a static method?

假设您绝对必须拥有一个静态方法?

You could get that with the following refactors:

您可以通过以下的重构来实现:

  • Introduce a Validatible interface&hellip;

  • 引入一个 Validatible 接口&hellip;

public interface Validatible{ 

    boolean isValid();

}
  • Make User a Validatiable&hellip;

  • User 类实现 Validatiable 接口&hellip;

public class User implements Validatible{
    ...

    @Override
    public boolean isValid(){
        ...
    }
    ... 
}
  • Simplify Validator&hellip;

  • 简化 Validator&hellip;

public interface Validator {

    ValidationResult validate(Validatible input);
}
  • Move your must-have static method to a utility/helper class&hellip;

  • 将您必须拥有的 static 方法移动到一个实用程序/辅助类中&hellip;

public class DeduperAnswer {

    static Validator validate(Predicate&lt;Validatible&gt; tester, String error) {
        return user -&gt; 
            tester.test(user) ? ValidationResult.valid() : 
                    ValidationResult.invalid(error);
    }
    ...
}

You could then call DeduperAnswer.validate() like I do in this demo&hellip;

然后,您可以调用 DeduperAnswer.validate() 就像我在这个演示中所做的一样&hellip;

Validator butWhatThen = DeduperAnswer.validate((user) -&gt; { return user.isValid(); }, &quot;not valid&quot;);

But like I asked in the comments, after you get back that Validator from the static method call, what do you intend to do with it then?

但是,就像我在评论中所问的,当您从 static 方法调用中获取了 Validator 后,您打算接下来如何使用它呢?

I've made the assumptions I've made because it's not 100% clear what your exact use case is. It would be super helpful if you would share that.

我做出了我的假设,因为您的确切用例不是百分之百清晰。如果您能分享一下,那将非常有帮助。

英文:

My first answer assumes you want nothing more than for the original code you posted to compile; with the fewest changes made to it. So that answer addresses only that assumption.

This is a different answer because it makes a different assumption; and requires more than one code change.

Assumption: You absolutely must have a static method?

You could get that with the following refactors:

  • Introduce a Validatible interface&hellip;

      public interface Validatible{ 
    
          boolean isValid();
    
      }
    
  • Make User a Validatiable&hellip;

      public class User implements Validatible{
          ...
    
          @Override
          public boolean isValid(){
              ...
          }
          ... 
      }
    
  • Simplify Validator&hellip;

      public interface Validator {
    
          ValidationResult validate(Validatible input);
      }
    
  • Move your must-have static method to a utility/helper class&hellip;

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

You could then call DeduperAnswer.validate() like I do in this demo&hellip;

    Validator butWhatThen = DeduperAnswer.validate((user) -&gt; { return user.isValid(); }, &quot;not valid&quot;);

But like I asked in the comments, after you get back that Validator from the static method call, what do you intend to do with it then?

I've made the assumptions I've made because it's not 100% clear what your exact use case is. It would be super helpful if you would share that.

huangapple
  • 本文由 发表于 2020年8月1日 15:36:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/63202894.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定