我想从打字稿代码库中建模一些接口和类。我想知道在 Java 中对 TypeScript 联合进行建模的最佳方法。 像这样的东西-
export type a = b | c | d | e | f;
export type b = {
..
}
export type c = {
..
}
..
在 Java 中对此进行建模的最佳方法是什么?
例如:
Class A = Class B or Class C or Class D;
这意味着 A 可以是任何这些类的对象。
我正在寻找课程的解决方案。
但另一个例子是。
export type numberString = string | number
这在 Java 中不存在,但其他基于 JVM 的语言可能有这样的概念(Scala 确实有 Trait,所以它们也不是不可能有 union)。
您可以使用 Java 进行替代:
(1) 使用重载:如果需要取一个
String
或 Number
,那么创建两个方法:
void foobar(int n) { ... }
void foobar(String s) { ... }
注意
int
不是 Integer
(原始类型与包装类型)...
(2) 使用泛型:如果需要对象实现某个接口(作为方法类型参数):
Runnable run1(Runnable runnable);
<E extends Runnable> E run2(E runnable);
<E extends Runnable & InterfaceA> E run3(E runnable);
run1
和 run2
基本相同:如果方法返回类型是 void
,则类型 E
可能没用。
<E extends Runnable & InterfaceA>
很少使用,但可以限制E
,使其实现类/接口Runnable
和InterfaceA
。
(3):你可以使用接口; Java不支持多重继承,但支持默认方法和多个接口:
interface B {}
interface A extends B, C, D, E, F {...}
问题是你不能让 A 的实现扩展 B、C、...、F 的实现。Java 中不存在此功能,但在某些语言中称为特征。
在这种情况下您可以使用委托:
class AImpl implements A {
private final B b;
public AImpl() {
this.b = new BImpl();
}
public void methodOfB() {b.methodOfB();}
// and so on
}
这不适用于数字和字符串,或任何无法更改继承模型的类型(最终类、第 3 方类等...)。
实际上,从 Java 17(更准确地说,Java 15+)开始就可以使用“Union 类型”。引入的
sealed
和 permits
关键字可用于声明“Union 类型”:
sealed interface Animal permits Dog, Cat {
}
final class Dog extends Animal {
public void bark() {
System.out.println("Woof!");
}
}
final class Cat extends Animal {
public void meow() {
System.out.println("Meow!");
}
}
Java可以识别这样的“联合类型”。例如,在 Java 21 中,当你写这样的东西时:
public class Test {
public static void main(String[] args) {
Animal animal = new Dog();
switch (animal) {
case Dog dog -> {
dog.bark();
}
case Cat cat -> {
cat.meow();
}
}
}
}
Java 不需要您添加冗余的
default
来使 switch 表达式变得“详尽”。但是,如果您将 sealed
关键字与 permits
一起删除,您将收到错误:
An enhanced switch statement should be exhaustive; a default label expected. Java(2099060)
此外,当您将
interface Animal
更改为 class Animal
时,您将收到相同的错误,因为 switch 表达式不考虑 Animal
本身,您必须添加另一个匹配项:
Animal animal = new Dog();
switch (animal) {
case Dog dog -> {
dog.bark();
}
case Cat cat -> {
cat.meow();
}
case Animal animal1 -> {
System.out.println("Unknown animal!");
}
}
没关系。 Java不再报错了。