scala - 在 Scala 中调用泛型类型的 "static function"

标签 scala generics

我试图在 Scala 中表示另一种语言的片段。我希望所有类都有一个自定义的 String 值来表示它们的类型。说到容器类,我遇到了麻烦。

我怎样才能抢到 typeName基于MyContainerClass[T <: MyType]的泛型参数?

object MyLang {

  trait MyType {
    protected val typeName: String
  }

  class MyString(val underlying: String) extends MyType {
    protected val typeName = "mystring"
  }

  class MyInt(val underlying: Int) extends MyType {
    protected val typeName = "myint"
  }

  class MyContainerClass[T <: MyType](val underlying: Seq[T]) extends MyType {
    // LINE THAT OBVIOUSLY DOESN'T WORK
    val typeName = T.typeName + "[]"
  }
}

我的第一个想法是获取 underlying 的元素并调用 typeName就可以了,但是如果 Seq[T]Nil ?

我的第二个想法是为所有扩展 MyType 的类创建一个 0 参数构造函数。 ,以便我可以调用 new T().typeName但这似乎并不困惑,并且无法强制所有类型的子类型包含具有特定签名的构造函数。

从这里我找到了 Manifests 和 TypeTags。我看到它们与我的问题有什么关系,但看不到它们将如何帮助我构建解决方案!

最佳答案

这种事情通常是用类型类来完成的:

trait TypeName[T] {
  def typeName: String
}

implicit object MyString extends TypeName[MyString] {
  def typeName = "mystring"
}

implicit object MyInt extends TypeName[MyInt] {
  def typeName = "myint"
}

class MyString(val underlying: String) extends MyType {
  val typeName = MyString.typeName
}
class  MyInt(val underlying: Int) extends MyType {
  val typeName = MyInt.typeName
}

class MyContainerClass[T <: MyType : TypeName](
  val underlying: Seq[T]
) extends MyType {
  val typeName = implicitly[TypeName[T]].typeName + "[]"
}

这个想法是,每当 MyContainerClass被创建,一个对应的实例TypeName被查找并隐式传递给构造函数,因此您可以在那里访问它并检索名称。

关于scala - 在 Scala 中调用泛型类型的 "static function",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48675692/

相关文章:

scala - 是否有工具或技术可以搜索兼容的较新版本的包依赖项?

scala - 如何实现单子(monad)解析?

scala - scala set.contains 的实现

swift - 如何在通用协议(protocol)上使用 if-let?

java - 为什么 compareTo() 有自己的实现体,而 Comparable 是一个接口(interface)?

具有通用参数类型的 Swift 函数

scala - 当我尝试运行此代码时,为什么会出现 java.lang.NoClassDefFoundError?

c# - 为什么我不能将泛型类型转换为值类型

spring - 在 Spring 中实例化泛型类 bean 的问题

scala - Spark graphx 多种边类型