我尝试了各种方法来完成一些非常简单的事情,这些事情我会在 Java 中使用装饰器模式来完成,但想在 Scala 中进行可堆栈修改,但失败了。
这是我的用例:我正在实现一些简单的自动完成器。它们都实现了一个基本特征:
trait AutoCompleter {
def topSuggestions(prefix: String): Iterator[String]
def update(sentence: String*): Unit
final def topSuggestions(prefix: String, n: Int): List[String] = topSuggestions(prefix).take(n).toList
}
其中一些是基于 trie 的自定义实现的具体实现:
/**
* This auto-completer learns from the user's input, and therefore does not require a preliminary dictionary.
*/
class ParrotAutoCompleter extends AutoCompleter {
private val trie = new WeightedTrie[Char, String]()
override def topSuggestions(prefix: String): Iterator[String] = trie.prefixedBy(prefix)
override def update(sentence: String*): Unit = sentence.foreach(trie += _)
}
其他一些是可堆叠的修改:
/**
* This auto-completer will try returning some suggestions when the prefix did not match any known word by dropping the
* last character until it finds a suggestion
*/
trait TolerantAutoCompleter extends AutoCompleter {
def MaxRetries: Int
abstract override def topSuggestions(prefix: String): Iterator[String] = {
if (MaxRetries < 1) throw new IllegalArgumentException("Should allow 1 retry minimum, but max retries was: " + MaxRetries)
for (attempt <- 0 to Math.min(prefix.length, MaxRetries)) {
val suggestions = super.topSuggestions(prefix.substring(0, prefix.length - attempt))
if (suggestions.hasNext) return suggestions
}
Iterator()
}
}
我这样使用它们:
val autoCompleter = new ParrotAutoCompleter with TolerantAutoCompleter { override val MaxRetries: Int = 5 }
此实现工作正常,但有一个缺陷:对 MaxRetries
执行健全性检查仅在使用自动完成器时而不是在创建自动完成器时才完成。更有趣的是,它每次都会运行,而不是只运行一次。
问题在于,特征中方法之外的任何代码都会立即执行,甚至在 MaxRetries
之前执行。已被覆盖(无论它是声明为 val
还是 def
)。
如何在构建时、覆盖之后执行健全性检查,并且不丢失可堆叠修改的属性?
最佳答案
当您重写 val MaxRetries = 5
时,您将创建一个仅在匿名类的构造函数中初始化的字段。构造函数的流程如下:
<jvm>: Initialize MaxRetries field to 0
<anon>: call super
TolerantAutoCompleter: call super
...
TolerantAutoCompleter: sanity check MaxRetries (still 0!)
TolerantAutoCompleter: return
<anon>: set MaxRetries to 5
<anon>: return
使用
new ParrotAutoCompleter with TolerantAutoCompleter { override def MaxRetries = 5 }
(使用def
)代替。
关于scala - 对特征中的抽象值进行健全性检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41947640/