如何以及何时在java中使用kotlin密封类?

bvuwiixz  于 2021-08-20  发布在  Java
关注(0)|答案(1)|浏览(439)

考虑到误用密封类,让我们看看下面的设计。
有两个模块: parser (kotlin)-负责从字符串生成示例 processor (java)-将原始传入数据泵入强类型存储器(即关系表)
字符串来自外部源到
processor processor 将其认可委托给
parser parser 创建不同类型的示例 [Banana, Nail, Shoe] 基于一些
rules X processor 基于某些属性将每个示例持久化到适当的表中 rules Y 在这里像这样使用密封类是否合适 parser 在那之后 processor 根据每个示例的具体类型做出决策?

// parser module exposes Item and its subclasses

sealed interface Item {
    class Banana(/*state 1*/) : Item
    class Nail(/*state 2*/) : Item
    class Shoe(/*state 3*/) : Item
}

fun parse(value: String, rule: ParseRule): Item {
    return when (true) {
        rule.canParseBanana(value) -> rule.makeBananaFrom(value)
        rule.canParseNail(value) -> rule.makeNailFrom(value)
        rule.canParseShoe(value) -> rule.makeShoeFrom(value)
        else -> throw RuntimeException("cannot parse")
    }
}    

// processor module makes decisions based on class 

void process(String value){
  Item item = parser.parse(value);

  if (item instance of Item.Banana){
    persistBanana((Item.Banana) item)
  } else if ( ... )
    // etc         
  } else {
     throw new RuntimeException("Unknown subclass of Item : " + item.getClass())
  }
}

我发现这种方法有点不对劲,因为越来越多的项的子类可能会导致设计灾难,但无法确定是否存在与此完全不同的密封类的“规范”用例。
当系统设计师更喜欢以下“类型较少”的东西时,密封类的适用性有什么限制:

class Item{
  Object marker; // String or Enum
  Map<String, Object> attributes;
}

// basically it is the same, but without dancing with types
void process(String value){
    Item item = parser.parse(value);

    if ("BANANA".equals(item.marker)){
      persistBanana(item.attributes)
    } else if (...){
      // etc
    }
}
bis0qfac

bis0qfac1#

您可以使用访问者模式提供 when .. is java的风格方法。

// Kotlin
abstract class ItemVisitor<OUT> {
    operator fun invoke(item: Item) = when (item) {
        is Banana -> visitBanana(item)
        is Shoe -> visitShoe(item)
        is Nail -> visitNail(item)
    }
    abstract fun visitBanana(item: Banana): OUT
    abstract fun visitShoe(item: Shoe): OUT
    abstract fun visitNail(item: Nail): OUT
}

因为物品是密封的,所以你不需要 else 那样的话 when 然后java代码可以创建访问者,而不是自己创建访问者 instanceof 与一名律师核实 else ,如果您添加了一个变体,那么您将添加一个方法,并得到提示,您的访问者的java实现需要新方法。

相关问题