将 predicate 强制转换为子类型

mbyulnm0  于 2021-07-08  发布在  Java
关注(0)|答案(2)|浏览(318)

我有一个 Predicate 我想用在一些操作中。然而,我有一个艰难的类型使多态性工作。
经过一些调查,我写了下面的最小代码来重现这个问题(这是一个比我能描述的更好的问题解释)。

class Custom implements Predicate<Integer> {
    int y;

    public Custom(int y) {
        this.y = y;
    }

    @Override
    public boolean test(Integer i) {
        return y+i>0;
    }
}

public class Main{

    public static void main(String[] args) {
            Custom c1 = new Custom(5);
            Custom c2 = new Custom(8);
            Custom c = (Custom) c1.and(c2); // faulty line - unable to cast
    }
}

我不知道为什么铸造失败,以及如何使它工作。

iugsix8n

iugsix8n1#

如果你想保持你的状态 Custom 对象并实现 Predicate 接口,我建议重载 and , or 以及 negate 方法。当你把两者结合起来 Custom 对象 and , or 或者当你打电话的时候 negate 你会得到一个 Custom 对象作为返回值。当你把一个 Custom 对象的任何其他实现 Predicate<Integer 方法仍将返回 Predicate<Integer :

class Custom implements Predicate<Integer> {

    class And extends Custom {

        Custom a;
        Custom b;

        public And(Custom a, Custom b) {
            super((i) -> a.test(i) && b.test(i));
            this.a = a;
            this.b = b;
        }
    }

    class Or extends Custom {

        Custom a;
        Custom b;

        public Or(Custom a, Custom b) {
            super((i) -> a.test(i) || b.test(i));
            this.a = a;
            this.b = b;
        }
    }

    class Not extends Custom {

        Custom custom;

        public Not(Custom custom) {
            super((i) -> !custom.test(i));
            this.custom = custom;
        }
    }

    private final Predicate<Integer> predicate;

    public Custom(int y) {
        this((i) -> y + i > 0);
    }

    private Custom(Predicate<Integer> predicate) {
        this.predicate = predicate;
    }

    @Override
    public boolean test(Integer i) {
        return predicate.test(i);
    }

    public Custom.And and(Custom other) {
        return new Custom.And(this, other);
    }

    public Custom.Or or(Custom other) {
        return new Custom.Or(this, other);
    }

    public Custom.Not negate() {
        return new Custom.Not(this);
    }

}
ruyhziif

ruyhziif2#

我看不出有什么好的理由来创建这样一种 predicate ,因为它会使 predicate 复杂化。然而,至少有3种不同的方式进入我的脑海“改变” predicate 状态。

v0-只需使用java.util.function.predicate

final Predicate<String> p1 = "foo"::equals;
final Predicate<String> unit1 = p1.or("bar"::equals);
Assertions.assertTrue(unit1.test("foo"));
Assertions.assertTrue(unit1.test("bar"));
Assertions.assertFalse(unit1.test("baz"));
final Predicate<String> unit2 = p1.or("baz"::equals);
Assertions.assertTrue(unit2.test("foo"));
Assertions.assertTrue(unit2.test("baz"));

这段代码没有什么问题,我仍然坚持不实现任何自定义类。

v1—自定义 predicate 实现中的“do cast”

这仍然需要来自 Predicate<T> 要重写的接口,以便在将来的java版本中不会中断。

public abstract class V1MutablePredicate<T, P extends V1MutablePredicate<T, P>>
        implements Predicate<T> {

    @Nullable
    private final Predicate<T> predicate;

    protected V1MutablePredicate(@Nullable final Predicate<T> predicate) {
        this.predicate = predicate;
    }

    protected abstract boolean doTest(T t);

    @Nonnull
    protected abstract P wrap(@Nonnull Predicate<T> predicate);

    @Override
    public final boolean test(final T t) {
        return predicate == null ? doTest(t) : predicate.test(t);
    }

    @Nonnull
    @Override
    public final P and(@Nonnull final Predicate<? super T> other) {
        return wrap(Predicate.super.and(other));
    }

    @Nonnull
    @Override
    public final P negate() {
        return wrap(Predicate.super.negate());
    }

    @Nonnull
    @Override
    public final P or(@Nonnull final Predicate<? super T> other) {
        return wrap(Predicate.super.or(other));
    }

}
private static final class Custom
        extends V1MutablePredicate<String, Custom> {

    private String s;

    Custom(final String s) {
        this(null, s);
    }

    private Custom(@Nullable final Predicate<String> predicate, final String s) {
        super(predicate);
        this.s = s;
    }

    @Override
    protected boolean doTest(final String t) {
        return t.equals(s);
    }

    @Nonnull
    @Override
    protected Custom wrap(@Nonnull final Predicate<String> predicate) {
        return new Custom(predicate, s);
    }

}

@Test
public void test() {
    final Custom p1 = new Custom("foo");
    final Custom p2 = new Custom("bar");
    final Custom unit = p1.or(p2);
    Assertions.assertTrue(unit.test("foo"));
    Assertions.assertTrue(unit.test("bar"));
    Assertions.assertFalse(unit.test("baz"));
    p2.s = "baz";
    Assertions.assertTrue(unit.test("foo"));
    Assertions.assertTrue(unit.test("baz"));
}

这似乎是最接近你想要完成的。

v2-从外部注入 predicate 状态

public final class V2MutablePredicate<T, S>
        implements Predicate<T> {

    private final Supplier<? extends S> stateSupplier;
    private final BiPredicate<? super S, ? super T> predicate;

    public V2MutablePredicate(final Supplier<? extends S> stateSupplier, final BiPredicate<? super S, ? super T> predicate) {
        this.stateSupplier = stateSupplier;
        this.predicate = predicate;
    }

    @Override
    public boolean test(final T t) {
        return predicate.test(stateSupplier.get(), t);
    }

}
final AtomicReference<String> r1 = new AtomicReference<>("foo");
final V2MutablePredicate<String, String> p1 = new V2MutablePredicate<>(r1::get, String::equals);
final AtomicReference<String> r2 = new AtomicReference<>("bar");
final V2MutablePredicate<String, String> p2 = new V2MutablePredicate<>(r2::get, String::equals);
final Predicate<String> unit = p1.or(p2);
Assertions.assertTrue(unit.test("foo"));
Assertions.assertTrue(unit.test("bar"));
Assertions.assertFalse(unit.test("baz"));
r2.set("baz");
Assertions.assertTrue(unit.test("foo"));
Assertions.assertTrue(unit.test("baz"));

此实现要求状态从管理要处理的多个对象的外部更改,还要求“state”类,但不要求重写默认方法,还要求供应商在每个 test 方法调用。

相关问题