在Java中表示匿名交集类型

3

这些都无法编译,但是我想表达匿名Java中的交集类型, 使得(A & B)表示实现/扩展A和B接口的任何类型,但通过使用某些语法组合类型来在代码中匿名表达。特别地,我想在以下情况下使用它们:

  1. 方法参数 例如public void foo((A & B) x) { ... }
  2. 方法返回类型 例如public (A & B) foo() { ... }
  3. 局部变量 例如(A & B) foo = ...
  4. 通配符泛型 例如List<? extends A & B)> foo = ...

我是否正确认为目前(Java 13)对我而言的选项如下?

  1. 方法参数 - 使用泛型:public static <T extends A & B> void foo(T x) { ... }
  2. 方法返回类型 - 使用泛型:public static <T extends A & B> T foo() { ... }
  3. 局部变量 - 使用 var var foo = (A & B) bar
  4. 通配符泛型 - 当前没有选项

以下文章深入探讨了这些类型何时/为什么能够有用。此 文章 很好地涵盖了1. 此 文章 涵盖了1. 2. 和 3. 这个 stackoverflow问题 涵盖了4.,并介绍了 Java 没有语法来实现它的有趣情况。

---编辑以解释我的使用情况如请求所示---

我经常使用只包含信息项的值对象。这些信息项相对独立且可重复使用,但通常只是为了方便而被聚合在一起,并传递给应用实际逻辑的其他类。我发现很容易以稳定和长期可重用的方式命名getter接口。关于getCustomerForename()getCustomerId()将返回什么,几乎没有争议,并且定义它们接近于为您的业务定义“数据模型”。但是,一旦您尝试将它们组合在一起,以创建一个Customer接口,该接口通常变得非常专用,并且不适当地在某些上下文中重复使用,其中您需要所有客户信息,在其他情况下,您只需要其中几个或与其他数据混合在一起。这很难命名,会创建不必要的耦合并创建额外的代码。相反,我想避免创建/命名任何新接口,而是使用匿名交集类型从公开每次只有一个getter的现有类型中创建新类型。因此,上述接口AB将是以下接口:

interface CustomerId {
  Long getCustomerId();
}

interface CustomerForename {
  String getCustomerForename();
}

如果我有一个报告只涉及这两项,我会创建带有“类型”(CustomerId&CustomerForename)的对象,而不是为了极少的好处命名和创建CustomerIdAndCustomerForename接口/类。

你是在问关于交叉类型可能性的1-4列表是否详尽,并且是否有任何选项可以从您的列表中实现第4点? - syntagma
此外,我认为使用反射可能也可以实现4,但这是否也是您感兴趣的? - syntagma
在我看来,对于4的需求只是糟糕软件设计的一个标志。1、2、3同样如此。这就是那种让人们编写糟糕代码的东西,就像那些无缘无故地到处使用lambda的人一样。 - akuzminykh
@syntagma 我部分地是想问是否还有其他我所不了解的上下文!反射也很有趣,但是.... - Anthony Leonard
@akuzminykh 你说得很对 - 任何过于晦涩的东西可能会起作用,但是如果太不习惯用语,没有人会使用它 :/ 但我认为探索可能性是有效的。我确实认为,那些被命名为提供完美“客户”对象但未能实现的无用特殊目的聚合类型也是“糟糕的设计”。 - Anthony Leonard
显示剩余4条评论
1个回答

1
如果您将类型参数指定为<T extends A&B>,则可以在通配符类型中使用它,就像以下示例中使用Optional<? extends T>一样。尽管我猜这与您想要做的类似,但我现在的大脑太疼了,无法解释其中的区别。

public class GenericsTest {

    public static void main(String[] args) {

        System.out.println(generateCombination().get().getB());
        System.out.println(generateCombination().get().getA());
    }

    static <T extends A&B> Optional<? extends T> generateCombination() {
        return (Optional<? extends T>) Optional.of(new Both());
    }

     interface A {
        String getA();
    }

     interface B {
        Number getB();
    }

    static class Both implements A, B {
        @Override
        public String getA() {
            return "Hello";
        }

        @Override
        public Number getB() {
            return 23;
        }
    }
}

无论如何,根据您的问题描述,其他变体似乎是正确的。


非常感谢您Jens :) 相信我,整个周末我的头都很疼!但我会再考虑一下可选方案,所以谢谢。 - Anthony Leonard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接