Как программно определить, является ли данный класс классом case или простым классом?
Как программно определить, является ли класс классом case или простым классом?
Ответ 1
В настоящее время (2011) вы можете использовать отражение, чтобы узнать, реализует ли класс интерфейс scala.Product
:
scala> def isCaseClass(o: AnyRef) = o.getClass.getInterfaces.find(_ == classOf[scala.Product]) != None
isCaseClass: (o: AnyRef)Boolean
scala> isCaseClass(Some(1))
res3: Boolean = true
scala> isCaseClass("")
res4: Boolean = false
Это просто приближение - вы можете пойти дальше и проверить, имеет ли он метод copy
, если он реализует Serializable
, если у него есть сопутствующий объект с соответствующим методом apply
или unapply
- в сущность, проверьте все вещи, ожидаемые от класса case, используя отражение.
Пакет отражения scala, входящий в один из следующих выпусков, должен облегчить и уточнить определение класса класса.
EDIT:
Теперь вы можете сделать это, используя новую библиотеку отражений scala - см. другой ответ.
Ответ 2
Использование нового API отображения Scala:
scala> class B(v: Int)
defined class B
scala> case class A(v: Int)
defined class A
scala> def isCaseClassOrWhat_?(v: Any): Boolean = {
| import reflect.runtime.universe._
| val typeMirror = runtimeMirror(v.getClass.getClassLoader)
| val instanceMirror = typeMirror.reflect(v)
| val symbol = instanceMirror.symbol
| symbol.isCaseClass
| }
isCaseClassOrWhat_$qmark: (v: Any)Boolean
scala> class CaseClassWannabe extends Product with Serializable {
| def canEqual(that: Any): Boolean = ???
| def productArity: Int = ???
| def productElement(n: Int): Any = ???
| }
defined class CaseClassWannabe
scala> isCaseClassOrWhat_?("abc")
res0: Boolean = false
scala> isCaseClassOrWhat_?(1)
res1: Boolean = false
scala> isCaseClassOrWhat_?(new B(123))
res2: Boolean = false
scala> isCaseClassOrWhat_?(A(321))
res3: Boolean = true
scala> isCaseClassOrWhat_?(new CaseClassWannabe)
res4: Boolean = false
Ответ 3
Если вы имеете в виду: Могу ли я определить, является ли класс классом case или не случайным классом программным путем, ответ отрицательный, но вы можете сделать приближение. Классы классов - это просто взлом компилятора, они сообщают компилятору о создании определенных методов и т.д. В финальном байт-коде нет никакой разницы между обычными классами и классами.
От Как класс case отличается от обычного класса?
- Вы можете выполнить сопоставление с шаблоном,
- Вы можете создавать экземпляры этих классов, не используя новые ключевое слово,
- Все аргументы конструктора доступны извне, используя автоматически создаваемые функции доступа,
- Метод toString автоматически переопределяется для печати имени класса case и всех его аргументов,
- Метод equals автоматически переопределяется для сравнения двух экземпляры одного и того же класса case, а не идентичность.
- Метод hashCode автоматически переопределяется для использования hashCodes аргументов конструктора.
Итак, вы можете создать класс case, просто определяя правильные методы и объекты-компаньоны самостоятельно.
Для того, чтобы узнать, может ли класс быть класс case, посмотрите на ответ от axel22.