6

我想在这些问题中实现方法链接:

实现支持方法链接的 Scala trait 的最佳实践

Scala DSL:使用无参数方法的方法链

但是,我希望一旦使用了“属性”,就不能再使用它了。例如,假设我有一个类“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 中搜索,但对我来说仍然有点模糊。

帮助将不胜感激!=)

4

2 回答 2

14

请参阅James Iry在 Haskell 和 Scala中的幻象类型。

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

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
                                ^
于 2013-07-26T14:30:50.047 回答
0

在这里您可以找到改进的解决方案:

http://jim-mcbeath.blogspot.fr/2009/09/type-safe-builder-in-scala-part-3.html

(实际上依赖于幻象类型)

于 2013-10-23T14:24:33.870 回答