【问题标题】:Plural Singletons for class with generic parameters具有泛型参数的类的复数单例
【发布时间】:2015-07-28 19:22:12
【问题描述】:

是否可以在 Scala 中为具有泛型参数的类定义单例?是的,它是复数形式,因为泛型参数的每个实例都必须有一个单例。我相信在最一般的情况下这是无稽之谈,但如果泛型参数是特定事物的子类型,我想知道它是否可行。

例如,将所有泛型参数的特定超类型视为此抽象类。

abstract class BaseType[T<:BaseType] {
  val omega:T;
}

这个想法是每个实现都有一个特殊的值,这就是欧米茄。现在我想要一个具有BaseType 子类型作为泛型参数的类:

class Thing[T<:BaseType[T]](val v:T, foo:Int);

因为每个T 都有特定的值omega,所以我希望Thing 包含omegafoo=0 的单例。我什至做不到

object Thing {
  def OmegaInstance[T<:BaseType[T]] = new Thing(/*what gos here?*/, 0);
}

但即使我可以,OmegaInstance 对于每次调用都会是新的,这是我不想要的。

有没有机会让它工作?

【问题讨论】:

  • 你肯定需要 T<:basetype thing>
  • 显然这将是 Java 方式。鉴于所有漂亮的类型技巧,我想知道 Scala 是否可以在这里创造一个小奇迹。
  • 在这种情况下,你应该有一些隐含的,可以提供 T<:basetype>

标签: scala generics singleton


【解决方案1】:

如果您的输入类型参数没有被删除,您可以实现相同的旧轻量级模式,但使用TypeTag 作为键:

import scala.reflect.runtime.universe._ 
import scala.collection.concurrent._

object Things {
   class Thing[T] private[Things]() { //private constructor, class itself is still accessable
       //...
   }

   private val map = TrieMap[TypeTag[_], Thing[_]]()

   def Thing[T: TypeTag] = 
          map.getOrElseUpdate(typeTag[T], new Thing[T]).asInstanceOf[Thing[T]] //`asInstanceOf` is safe here

}

用法示例:

import Things._

scala> Thing[Int]
res2: Things.Thing[Int] = Things$Thing@4472abe8 //new object

scala> Thing[Int]
res3: Things.Thing[Int] = Things$Thing@4472abe8 //same object

scala> Thing[Int]
res4: Things.Thing[Int] = Things$Thing@4472abe8 //same object

scala> Thing[String]
res5: Things.Thing[String] = Things$Thing@4745c8d2 //new object

scala> Thing[String]
res6: Things.Thing[String] = Things$Thing@4745c8d2 //same object

你可以在这里用任何参数实例化你想要的任何东西。用法看起来几乎就像拥有泛型参数化的object(每个泛型一个单例)。

【讨论】:

    猜你喜欢
    • 2010-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-18
    • 1970-01-01
    相关资源
    最近更新 更多