呼叫“a”;“静态功能”;在Scala中属于泛型类型

呼叫“a”;“静态功能”;在Scala中属于泛型类型,scala,generics,Scala,Generics,我试图用Scala表示另一种语言的片段。我希望所有类都有一个表示其类型的自定义字符串值。当涉及到容器类时,我遇到了麻烦 如何根据MyContainerClass[T的泛型参数获取typeName,这类事情通常是通过类型类完成的: trait TypeName[T] { def typeName: String } implicit object MyString extends TypeName[MyString] { def typeName = "mystring" } impl

我试图用Scala表示另一种语言的片段。我希望所有类都有一个表示其类型的自定义字符串值。当涉及到容器类时,我遇到了麻烦


如何根据MyContainerClass[T的泛型参数获取
typeName
,这类事情通常是通过类型类完成的:

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 + "[]"
}
trait TypeName[T]{
def typeName:String
}
隐式对象MyString扩展TypeName[MyString]{
def typeName=“mystring”
}
隐式对象MyInt扩展类型名[MyInt]{
def typeName=“myint”
}
类MyString(val底层:String)扩展了MyType{
val typeName=MyString.typeName
}
类MyInt(val-underlined:Int)扩展了MyType{
val typeName=MyInt.typeName
}

类MyContainerClass[T我认为@Dima的答案很好,我实际上是在写同样的代码,但他比我快。因此,我将提供另一种解决方案。如果您同意使用真实的类名:

import scala.reflect._

object MyLang {

  trait MyType {
    val typeName = this.getClass.getName
  }

  class MyString(val underlying: String) extends MyType

  class MyInt(val underlying: Int) extends MyType

  class MyContainerClass[T <: MyType](val underlying: Seq[T])
    (implicit tag: ClassTag[T])
    extends MyType {
    override val typeName = s"${getClass.getName}[${tag.runtimeClass.getName}]"
  }
}
您甚至可以将
typeName
定义为元组
(父类、子类)
或任何其他包含
java.lang.class[\u]
的非字符串数据类型

问题实际上是Scala不允许您覆盖静态方法,因为它没有这些方法。您可以在某种程度上用
对象
方法模拟它们


在您的例子中,您试图使用一个实例变量
typeName
,但您无法从类中获取它,因为它不是实例。在这种情况下,您需要一些位置来保存该值,如@Dima的answer-object中,您根据类型隐式查找该对象。缺点是您必须为每种类型创建它们

对于只寻找已接受答案的最小实现的任何人来说,只需要定义一些trait
Y[T]
、类
Z
、以及扩展
Y
的隐式对象
Z

object TypeClassTest {
    trait X

    trait Y[T] {
        def t: T
    }

    // Class with "static" method `t`
    class Z extends X

    // "static" method defined
    implicit object Z extends Y[String] {
        override def t = "t"
    }

    // Using 'static' method of the generic type
    class A[T <: X : Y](underlying: T) {
        val t: T = implicitly[Y[T]].t
    }
}
对象类型类测试{
性状X
性状Y[T]{
定义t:t
}
//使用“静态”方法初始化`t`
类Z扩展了X
//定义的“静态”方法
隐式对象Z扩展Y[字符串]{
覆盖def t=“t”
}
//使用泛型类型的“静态”方法

class A[T你可以只做
tag.toString
。这和我的解决方案实际上是一样的:
ClassTag
扮演着类型class的角色。“pro”是指它已经为每个类定义了,当然是“con”,你不能自定义名称。
scala> new MyLang.MyContainerClass(Seq(new MyLang.MyString("abc"))).typeName

res0: String = MyLang$MyContainerClass[MyLang$MyString]
object TypeClassTest {
    trait X

    trait Y[T] {
        def t: T
    }

    // Class with "static" method `t`
    class Z extends X

    // "static" method defined
    implicit object Z extends Y[String] {
        override def t = "t"
    }

    // Using 'static' method of the generic type
    class A[T <: X : Y](underlying: T) {
        val t: T = implicitly[Y[T]].t
    }
}