Scala: Как получить класс композиции микшина?
scala> import java.util.Properties
import java.util.Properties
scala> trait Foo extends Properties
defined trait Foo
scala> classOf[Foo]
res0: java.lang.Class[Foo] = interface Foo
scala> class FooP extends Foo
defined class FooP
scala> classOf[FooP]
res1: java.lang.Class[FooP] = class FooP
scala> classOf[Properties with Foo]
<console>:7: error: class type required but java.util.Properties with Foo found
classOf[Properties with Foo]
^
scala> new Properties with Foo
res2: java.util.Properties with Foo = {}
scala> res2.getClass
res3: java.lang.Class[_] = class $anon$1
Есть ли способ получить класс "Свойства с помощью Foo" без создания экземпляра или нового класса?
Ответы
Ответ 1
classOf[X]
работает только в том случае, если X
соответствует физическому классу. T with U
является составным типом и не соответствует классу.
Вы можете использовать Манифесты для определения стирания типа. Стирание типа T with U
равно T
.
scala> trait T
defined trait T
scala> trait U
defined trait U
scala> manifest[T with U]
res10: Manifest[T with U] = T with U
scala> manifest[T with U].erasure
res11: java.lang.Class[_] = interface T
Здесь вы можете видеть, что List[Int]
и List[_]
имеют одно и то же стирание:
scala> classOf[List[_]]
res13: java.lang.Class[List[_]] = class scala.collection.immutable.List
scala> classOf[List[Int]]
res14: java.lang.Class[List[Int]] = class scala.collection.immutable.List
scala> classOf[List[Int]] == classOf[List[_]]
res15: Boolean = true
Ответ 2
Нет, это невозможно, потому что "X с Y" является анонимным определением в вашем примере. Это не относится к тому, что "класс X расширяет Z с Y", конечно.
Ответ 3
Вы не можете получить литерал класса, но вы можете проверить, соответствует ли объект этому типу двумя разными способами:
trait X
trait Y
val xy: AnyRef = new X with Y
val zz: AnyRef = new Object with X
xy.isInstanceOf[X with Y] // true
zz.isInstanceOf[X with Y] // false
xy match { case a: X with Y => true; case _ => false} // true
zz match { case a: X with Y => false; case _ => false} // false
Это похоже на это общее объявление в java
public <T extends Comparable<T> & Serializable> T id(T t) { return t; }
Этот метод стирается до
public Comparable id(Comparable t) { return t; }
Однако в Java вы не можете сказать xy instanceof (X&Y)
, но это действительно так же, как xy instanceof X && xy instanceof Y
Ответ 4
Я не уверен, что вы пытаетесь сделать с составным классом, но что вы можете сделать, это получить список реализованных интерфейсов и суперкласс заданного анонимного класса, которого может быть достаточно. Например:
trait X
trait Y
class Foo
val bar = new Foo with X with Y
val barClass = bar.getClass // class $anon$1
barClass.getInterfaces // Array(interface X, interface Y)
barClass.getSuperclass // class Foo