我有以下情况:两个验证助手
StringValidationHelper ...
public class StringValidationHelper {
public static Validation<String> notNull =
SimpleValidation.from(s -> s != null, "must not be null.");
public static Validation<String> moreThan(int size) {
return SimpleValidation.from(
s -> s.length() >= size,
String.format ("must have more than %s chars.", size));
}
... // More methods (lessThan, etc)}
...和NumberValidationHelper。
public class NumberValidationHelper {
public static Validation<Number> notNull =
SimpleValidation.from(n -> n != null, "must not be null");
public static <N extends Number & Comparable<N>> Validation<N> lowerThan(N max){
return SimpleValidation.from(
n -> n.compareTo(max) == -1,
String.format("must be lower than %s.", max));
}
... // More methods like (greaterThan, etc)}
来自的方法是一个静态工厂方法,它接收谓词,并且一条消息提示最终验证失败。
public class SimpleValidation<K> implements Validation<K>{
private Predicate<K> predicate;
private String onErrorMessage;
private SimpleValidation(Predicate<K> predicate, String onErrorMessage) {
this.predicate = predicate;
this.onErrorMessage = onErrorMessage;
}
public static <K> SimpleValidation<K> from(Predicate<K> predicate, String onErrorMessage){
return new SimpleValidation<>(predicate, onErrorMessage);
}
... // Omitted for simplicity
}
借助Validation界面,您可以享受异常流畅的界面
@FunctionalInterface
public interface Validation<K> {
... // Omitted for simplicity
default Validation<K> and(Validation<K> other) {
return param -> {
ValidationResult firstResult = this.test (param);
return ! firstResult.isValid()? firstResult: other.test(param);
};
}
... // Omitted for simplicity
}
因此,例如,我可以使用闭包notNull开始验证。
示例:使用NumberValidationHelper
public class MyValidate {
void validate(int toValidate) {
notNull.and(lowerThan(100)).test(toValidate).isValid();
}
}
这验证框架我开发了基于此文章。
好吧,notNull包含与类型无关的行为,因此我想删除这两个帮助程序的重复项。我在不丢失流体界面的情况下找不到明显的形状。
由于变量是静态的,因此,例如,您不能使用泛型并扩展行为。
public abstract class GenericHelper<K> {
public static Validation<K> notNull = SimpleValidation.from(o -> o != null, "must not be null.");
}
同样,键入以下带有对象的验证也不会打扰我:
public abstract class GenericHelper {
public static Validation<Object> notNull = SimpleValidation.from(o -> o != null, "must not be null.");
}
...因为在调用链中,它将产生编译错误,因为notNull的结果将是Validation <Object>,并且将期望Validation <Integer>
notNull.and(lowerThan(100)).test(toValidate).isValid(); //Does not compile
有什么方法可以使用Java 8功能特性来使该接口保持通用状态,而与我上面尝试过的解决方案背道而驰?
感激的
您应该放宽的通用签名and
,允许Validation<T>
使用更具体的T
as参数来生成Validation<T>
as结果:
default <T extends K> Validation<T> and(Validation<T> other) {
return param -> {
ValidationResult firstResult = this.test(param);
return ! firstResult.isValid()? firstResult: other.test(param);
};
}
坚持你的例子,你仍然不能写
void validate(int toValidate) {
notNull.and(moreThan(100)).test(toValidate).isValid();
}
作为moreThan
回报Validation<String>
哪些不可以test
的int
,但斑点这样的错误是什么泛型是所有关于(我想,你有另一个moreThan
在您的实际代码库方法,你没有在你的问题包括)。但是以下内容现在可以与您的示例一起使用:
void validate(int toValidate) {
notNull.and(lowerThan(100)).test(toValidate).isValid();
}
有时,您需要先测试更具体类型的验证,然后才能进行更通用的验证,而该验证仍然不适用于上述方法。一种解决方案是与JDK开发人员走同一条路线,并Function.andThen(after)
添加一个Function.compose(before)
,以交换角色
default <T extends K> Validation<T> compose(Validation<T> other) {
return param -> {
ValidationResult firstResult = other.test(param);
return ! firstResult.isValid()? firstResult: this.test(param);
};
}
或者您创建一个static
方法,该方法允许两个参数都具有比结果更大的类型Validation
:
static <T> Validation<T> and(Validation<? super T> first, Validation<? super T> second) {
return param -> {
ValidationResult firstResult = first.test(param);
return ! firstResult.isValid()? firstResult: second.test(param);
};
}
请注意,该static
方法可以与便捷的实例方法结合使用,以便调用者仅static
在遇到通用签名的限制时才诉诸该方法:
@FunctionalInterface
public interface Validation<K> {
ValidationResult test(K item);
default <T extends K> Validation<T> and(Validation<T> other) {
return and(this, other);
}
static <T> Validation<T> and(Validation<? super T> first,Validation<? super T> second){
return param -> {
ValidationResult firstResult = first.test(param);
return ! firstResult.isValid()? firstResult: second.test(param);
};
}
}
所以你仍然可以写
notNull.and(lowerThan(100)).test(toValidate).isValid();
但是当达到限制时,例如
Validation<Object> anotherCriteria;
…
lowerThan(100).and(anotherCriteria).test(toValidate).isValid();
不起作用,您可以求助于
Validation.and(lowerThan(100), anotherCriteria).test(toValidate).isValid();
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句