Как я могу определить класс объекта в Scala?

Мне нужно проверить, что у строго экземпляр bar, а не foo. Как я могу сделать это в Scala?

trait foo {}

trait bar extends foo {}

val x = new foo {}
val y = new bar {}

x.isInstanceOf[foo] // true
x.isInstanceOf[bar] // false

y.isInstanceOf[bar] // true
y.isInstanceOf[foo] // true (but I want it to return false)

2 ответа

Решение

Название вашего вопроса говорит класс, но фактический вопрос использует черты. Вы можете сделать что-то подобное через отражение во время выполнения с классами. Давайте создадим удобный метод для получения reflect.runtime.universe.Type объекта:

import scala.reflect.runtime.universe._

def tpeOf[A](a: A)(implicit tt: TypeTag[A]): Type = tt.tpe

И несколько примеров классов:

class Foo
class Bar extends Foo
val x = new Foo
val y = new Bar

Мы можем использовать наши tpeOf метод получения Type из x а также yи сравнить его с Type из TypeTag получено с помощью typeOf, Это даст результаты, которые вы хотите.

scala> tpeOf(x) =:= typeOf[Foo]
res0: Boolean = true

scala> tpeOf(x) =:= typeOf[Bar]
res1: Boolean = false

scala> tpeOf(y) =:= typeOf[Foo]
res2: Boolean = false

scala> tpeOf(y) =:= typeOf[Bar]
res3: Boolean = true

Но это не работает для черт, потому что в вашем примере y не является примером barэто экземпляр анонимного класса, который расширяет bar, Таким образом, использование этого метода всегда приведет к false,

trait foo {}
trait bar extends foo {}
val x = new foo {}
val y = new bar {}

scala> tpeOf(x) =:= typeOf[bar]
res4: Boolean = false   // As expected, `x` is not exactly `bar`

getClass будет работать, если вы просто создадите новые экземпляры. Но вы создаете новые анонимные классы и их экземпляры.

Для них отношение к foo и bar точно такое же: они являются суперклассами.

Другие вопросы по тегам