Как программно определить, является ли класс падежным классом или простым классом? - PullRequest
14 голосов
/ 23 сентября 2011

Как программно определить, является ли данный класс классом случая или простым классом?

Ответы [ 3 ]

22 голосов
/ 02 марта 2014

Использование нового 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 голосов
/ 23 сентября 2011

В настоящее время (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, входящий в один из следующих выпусков, должен упростить и точнее определить класс дел.

РЕДАКТИРОВАТЬ:

Теперь вы можете сделать это с помощью новой библиотеки Scala Reflection -см. другой ответ.

2 голосов
/ 23 сентября 2011

Если вы имеете в виду: Могу ли я определить, является ли класс классом прецедентов или классом, не являющимся прецедентами, ответом будет «нет», но вы можете сделать приближение. Классы case - это просто взлом компилятора, они сообщают компилятору о создании определенных методов и т. Д. В последнем байт-коде нет разницы между обычными классами и классами case.

С Чем класс дел отличается от обычного класса?

  1. Вы можете сделать сопоставление с образцом на нем,
  2. Вы можете создавать экземпляры этих классов, не используя новые ключевое слово
  3. Все аргументы конструктора доступны извне с помощью автоматически сгенерированные функции доступа,
  4. Метод toString автоматически переопределяется для печати имени класса case и всех его аргументов,
  5. Метод equals автоматически переопределяется для сравнения двух экземпляры одного и того же класса дел структурно, а не по идентичности.
  6. Метод hashCode автоматически переопределяется для использования hashCodes аргументов конструктора.

Таким образом, вы можете создать класс case, просто определив правильные методы и сопутствующие объекты.

Чтобы узнать, как узнать, может ли класс быть классом case, посмотрите ответ из axel22.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...