scala - 类型安全的方法链,不允许重复操作

标签 scala method-chaining

我想像这些问题一样实现方法链接:

Best practice to implement Scala trait which supports method chaining;

Scala DSL: method chaining with parameterless methods

但是,我希望一旦使用了“属性”,就不能再使用它了。
例如,假设我有一个类“Myclass”,对于该类我最多允许一次使用定义“foo”和定义“bar”,并且我不在乎最终的返回类型。因此:

val c = new Myclass
c foo //ok !
c foo bar // ok!
c foo foo // refuse to compile
c foo bar foo //refuse to compile

我在这个问题上苦苦挣扎了一段时间,我的视线开始变得模糊!
但是,我尝试使用隐式类,它们是否需要解析未使用关联属性的对象,并且我找不到方法,是否需要通过从对象可用属性中删除它来“消耗”该属性,以及,再次,我找不到方法。

我目前正在搜索反射API,但对我来说还是有点晦涩。

帮助将不胜感激! =)

最佳答案

参见Phantom Types In Haskell and ScalaJames Iry

您还可以使用类型安全的构建器模式:

trait TTrue
trait TFalse

@annotation.implicitNotFound(msg = "Cannot call same method twice.")
sealed abstract class =^=[From, To]
object =^= {
  private val singleton_=^= = new =^=[Any, Any]{}
  implicit def tpEquals[A]: A =^= A = singleton_=^=.asInstanceOf[A =^= A]
}

class Myclass[TFoo, TBar, TBuz] private(){
  def foo(implicit e: TFoo =^= TFalse) = new Myclass[TTrue, TBar, TBuz]
  def bar(implicit e: TBar =^= TFalse) = new Myclass[TFoo, TTrue, TBuz]
  def buz(implicit e: TBuz =^= TFalse) = new Myclass[TFoo, TBar, TTrue]
}

object Myclass{
  def apply() = new Myclass[TFalse, TFalse, TFalse]
}

这样使用
scala> Myclass().foo.bar.buz
res0: Myclass[TTrue,TTrue,TTrue] = Myclass@12ac706a

scala> Myclass().bar.buz.foo
res1: Myclass[TTrue,TTrue,TTrue] = Myclass@1e69dff6

scala> Myclass().foo.buz.foo
<console>:12: error: Cannot call same method twice.
              Myclass().foo.buz.foo
                                ^

关于scala - 类型安全的方法链,不允许重复操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17882998/

相关文章:

javascript - 为什么我的 'this' 没有在每个循环内部 jQuery 中更改上下文?

scala - 无法编译 scrooge thrift 插件生成的源代码

scala - 如何使用specs2检查Future[Seq[T]]是否为空

Javascript 柯里化(Currying)与方法链

php - 如何在 PHP5 中构建多 oop 函数

c++ - 从方法链中使用的临时 move

javascript - 有没有好的方法来管理 CDN 提供的 javascript 依赖项?

scala - 元组到 Spark Scala中的数据帧

scala - 为什么 sbt 不在这里获取作用域值?

c++ - 有没有办法用一行在同一个对象上调用多个函数?