scala - 对特征中的抽象值进行健全性检查

标签 scala abstract traits

我尝试了各种方法来完成一些非常简单的事情,这些事情我会在 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/

相关文章:

scala - Akka Streams 中的 Monadic 短路

scala - Spark 结构化流 - 将静态数据集与流数据集连接起来

c++ - 如何在 switch 语句中正确初始化不同的派生类?

java - 抽象方法的目的是什么?

scala - 列表缓冲区前置 : error: value++=: is not a member of Seq[Int]

scala - Some(string.!!) 在 Scala 中是什么意思?

database - 在未知数据库中存储 IPv6 的最佳方式?

generics - 如何避免将具体结构更改为通用结构所产生的链式 react ?

rust - 在 Rust 中为什么需要类型注释,即使它们在通用特征中明确指定

generics - 为什么我不能用 let _ : Arc<dyn Trait> = value. into() 创建一个 trait 对象?