如何获得混合特征的具体 class

How to get the concrete class for a mixed in trait

假设我有以下特征并且 classes:

trait A {
    def foo(): Unit
}

trait B extends A {
    abstract override def foo(): Unit = {
        // Can I determine the name of the concrete class here?
        super.foo()
    }
}

class C extends A {
    def foo() = {
        println("C::foo()")
    }
}

val c = new C with B
c.foo()

有没有办法从特征 B 中确定实例化它的具体 class 的名称?即 C

尝试.getClass.getSuperclass.getSimpleName

trait A {
  def foo(): Unit
}

trait B extends A {
  abstract override def foo(): Unit = {
    println("B is instantiated in " + getClass.getSuperclass.getSimpleName)
    super.foo()
  }
}

class C extends A {
  def foo() = {
    println("C::foo()")
  }
}

val c = new C with B
c.foo()
//B is instantiated in C
//C::foo()

让我们稍微修改一下您的代码,因为它无法编译。当从 B 调用 super.foo 时,你会得到一个异常,因为它没有实现。

package test

object HelloWorld1 {
  trait A {
    def foo(): Unit
  }

  trait B extends A {
    override def foo(): Unit = {
      println(getClass.getName)
      // Can I determine the name of the concrete class here?
    }
  }

  class C extends B {  }

  class D extends B { }

  def main(args: Array[String]): Unit = {
    val c = new C
    c.foo()
    val d = new D
    d.foo()
  }
}

根据该代码,您可以调用 getClass.getName,它将提供一个字符串,该字符串由完整的包名称和当前的 class 构成。

在给定的示例中,您将得到:

test.HelloWorld1$C
test.HelloWorld1$D

如果你在 HelloWorld1 之外使用 classes C 和 D,你将得到:

C
D

如果你只想在第一个选项中获得CD,即在HelloWorld1中,你可以调用getClass.getSimpleName而不是getClass.getName

还有一个选择。您还可以使用 getClass.getCanonicalName$ 替换为 ..