Scala 应用不带参数

Scala apply with no parameters

我想创建一个程序,在收到请求时生成随机的东西,例如下面示例中的字母。我已经定义了一个抽象 class 和一个伴随对象到 return 子 class 之一。

  abstract class Letter

  class LetterA extends Letter {
    override def toString = "A"
  }
  class LetterB extends Letter {
    override def toString = "B"
  }
  class LetterC extends Letter {
    override def toString = "C"
  }

  object Letter {
    def apply = RNG.d(3) match {
      case 1 => new LetterA
      case 2 => new LetterB
      case 3 => new LetterC
    }
    override def toString = "Random Letter"
  }

我的梦想是我将能够使用 Letter 来获得类型为 A、B 或 C 的随机字母。但是使用这段代码,它只给了我字母对象。 Letter.apply 给我 A、B 或 C,但很丑。

如果我将 apply 函数更改为 apply() 那么事情会好一些,因为我可以使用 Letter() 来获取我的随机字母之一,但是 Letter 仍然给我对象。

有什么我可以做的,以便将某些东西分配给 Letter 实际上解析为 LetterALetterBLetterC 之一?

你的问题的答案是否定的,你无法区分 Letter.type 和 Letter.apply,所以你需要一个解决方法。

我建议你使用 Type-Class 模式,它比向伴随对象添加随机生成的应用方法更具扩展性

  trait RandomGenerator[T] {
    def gen: T        
  } 

  implicit object RandomLetter extends RandomGenerator[Letter] {

    private val rnd = new Random()

    def gen = (rnd.nextInt(3) + 1) match {
      case 1 => new LetterA
      case 2 => new LetterB
      case 3 => new LetterC
    }
  }

  def random[T: RandomGenerator]: T = 
    implicitly[RandomGenerator[T]].gen


  println(random[Letter])
  println(random[Letter])
  println(random[Letter])

您可以在伴随对象中提供从 Letter.typeLetter 的隐式转换:

implicit def asLetter(companion: Letter.type): Letter = companion.apply

然后你可以使用Letter得到一个可以隐式转换为Letterclass的对象。例如:

val x: Letter = Letter
val letters: Seq[Letter] = Seq.fill(10)(Letter)

但请记住,这样您将始终必须将对象归因于正在使用的 class。

注意:我不认为这是一个特别好的主意,但我只是想证明这是可能的!

您可以将 Letter 变成 def(如有必要,在包对象上)。为简单起见,我将东西包装在外部对象中:

object Letters {
  // Your class definitions
  def Letter = RNG.d(3) match {
    case 1 => new LetterA
    case 2 => new LetterB
    case 3 => new LetterC
  }
}

使用大写名称的 def 不是很惯用,但出于某些 DSL 的考虑,IMO 可以接受。