Typescript union 有 Java 等价物吗?

问题描述 投票:0回答:2

我想从打字稿代码库中建模一些接口和类。我想知道在 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 typescript
2个回答
3
投票

这在 Java 中不存在,但其他基于 JVM 的语言可能有这样的概念(Scala 确实有 Trait,所以它们也不是不可能有 union)。

您可以使用 Java 进行替代:

  1. 使用重载。
  2. 使用泛型。
  3. 使用界面(可能是最接近您正在寻找的界面)

(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 方类等...)。


0
投票

实际上,从 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不再报错了。

© www.soinside.com 2019 - 2024. All rights reserved.