且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

类型安全生成器:如何组合幻像类型

更新时间:2022-01-03 09:05:37

你走在正确的轨道上,你只需要添加一点类型细化:

You were on the right track, you just needed to add a little type refinement:

trait BuilderMethods {
  type FooCalled <: TBoolean
  type BarCalled <: TBoolean
}

class Builder[M <: BuilderMethods] private() {
  def foo()(implicit ev: M#FooCalled =:= TFalse): Builder[M {type FooCalled = TTrue}] = {
    new Builder[M {type FooCalled = TTrue}]
  }
  def bar()(implicit ev: M#BarCalled =:= TFalse): Builder[M {type BarCalled = TTrue}] = {
    new Builder[M {type BarCalled = TTrue}]
  }
}

object Builder {
  type UnusedBuilder = BuilderMethods {type FooCalled = TFalse; type BarCalled = TFalse;}
  def apply(): Builder[Builder.UnusedBuilder] = new Builder[UnusedBuilder]()
}

object TestPhantomStruct extends App {
  val newBuilder = Builder()
  val builderFooCalled = newBuilder.foo()
  val builderFooCalledTwice = builderFooCalled.foo() // will not compile
  val builderFooCalledBarCalled = builderFooCalled.bar()
  val builderFooCalledTwiceBarCalled = builderFooCalledBarCalled.foo() // will not compile

  val builderBarCalled = newBuilder.bar()
  val builderBarCalledTwice = builderBarCalled.bar() // will not compile
}