0

Can someone please explain the difference between classOf[DataModel] and DataModel.getClass()?

Here DataModel is a case class.

Anurag
  • 353
  • 3
  • 15
  • 2
    Well, one is a function that you can call given a type, and the other is a method that you can call given a value. - Note, if you call `DataModel.getClass` you are getting the `Class` of the _syntethic class_ of the companion object of `DataModel`, rather than the `Class` of the `DataModel` type. – Luis Miguel Mejía Suárez Feb 27 '23 at 19:05
  • Thanks, this helps. Is there any online resource you aware of about this? Tried searching but couldn't find any. :/ – Anurag Feb 28 '23 at 14:09
  • 1
    It depends what you mean with _"this"_, what I said can just be derived if you understand the basis of the language _(to distinguish a `class` / `trait` from its companion `object`)_, understanding the difference between types and classes, and understanding singleton types. – Luis Miguel Mejía Suárez Feb 28 '23 at 14:37

1 Answers1

1

Firstly, DataModel in DataModel.getClass() refers not to the case class DataModel but to its companion object

Class companion object vs. case class itself

But suppose you meant classOf[DataModel] vs. DataModel(...arguments...).getClass().

One more possible confusion here is between compile time and runtime

Runtime vs. Compile time

In classOf[DataModel] the class DataModel must be known at compile time. You're using its type DataModel in a type position [DataModel] in classOf[DataModel]. (*)

In DataModel(...).getClass() you're calling the method .getClass() on an instance DataModel(...) of the case class. So you're calling it at runtime

trait Parent
case class DataModel(/*...*/) extends Parent
// static (compile-time) type of x is Parent, dynamic (runtime) type is DataModel 
val x: Parent = DataModel(/*...*/)
x.getClass // class DataModel

In the latter case the class even can be not known at compile time at all, for example can be generated at runtime

import scala.reflect.runtime.{currentMirror => rm}
import scala.reflect.runtime.universe.Quasiquote
import scala.tools.reflect.ToolBox
val tb = rm.mkToolBox()

val symbol = tb.define(q"case class DataModel() extends Parent")
val x: Any = tb.eval(q"new $symbol()")
x.getClass // class __wrapper....DataModel

(*) Well, if this is really necessary you can actually call classOf[DataModel] even at runtime for runtime-generated class DataModel by means of runtime compilation (toolbox) again (in such case you create a new compile time inside the runtime)

tb.eval(q"classOf[$symbol]").asInstanceOf[Class[_]] // class __wrapper....DataModel

You can read also about the difference between type and class

What is the difference between Type and Class?

What is the difference between a class and a type in Scala (and Java)?

https://typelevel.org/blog/2017/02/13/more-types-than-classes.html

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66