Reputation: 1
I went trough scaladoc and found something that I find strange and I cannot explain. There is the
sealed abstract class Vector
with its companion object Vector
.
Looking through Vector.scala
it looks like that the following is happening
val test: Vector[Int] = Vector(1,2,3)
Here I am calling the apply method of the companion object which is using some factory method to create an object that is a subclass of Vector
and has a concrete implementation. So the real type of test is not Vector[Int]
but some other subclass.
When I now print the class
print(test.getClass())
it returns Vector
which is an abstract class so the object can't be of type Vector
.
Is there a way to print the actual class of the object? Similar to when I create my own class without an overriding toString
scala uses the toString
implementation of Any(?)
to print out myClass@memorLocation
.
Upvotes: 0
Views: 193
Reputation: 48420
Use getClass
to get the runtime class of an object. The rest of the answer expands on Luis' comment.
Scala 2.13.2 introduced implementation subclasses for Vector
A second major difference lies in the implementation. Whereas the old
Vector
uses a single class for collections of all supported sizes, the new one is split intoVector0
toVector6
for the different dimensions of the main data array.Vector0
is a singleton object for the empty vector,Vector1
(used for collections up to size 32) is essentially the same asArraySeq
, all higher dimensions are finger trees.
/* Contents of Vector.scala in 2.13.2 */
object Vector extends StrictOptimizedSeqFactory[Vector]
sealed abstract class Vector[+A] ...
private sealed abstract class VectorImpl[+A](...) extends Vector[A]
private sealed abstract class BigVector[+A](...) extends VectorImpl[A]
private object Vector0 extends BigVector[Nothing]
private final class Vector1[+A](...) extends VectorImpl[A]
private final class Vector2[+A](...) extends BigVector[A]
private final class Vector3[+A](...) extends BigVector[A]
private final class Vector4[+A](...) extends BigVector[A]
private final class Vector5[+A](...) extends BigVector[A]
private final class Vector6[+A](...) extends BigVector[A]
...
which were not present in Scala 2.13.1
/* Contents of Vector.scala in 2.13.1 */
object Vector extends StrictOptimizedSeqFactory[Vector]
final class Vector[+A] ...
...
Hence the runtime class of Vector(1)
in 2.13.2 is Vector1
Welcome to Scala 2.13.2 (OpenJDK 64-Bit Server VM, Java 1.8.0_202).
Type in expressions for evaluation. Or try :help.
scala> Vector(1).getClass.getCanonicalName
val res0: String = scala.collection.immutable.Vector1
whilst the runtime class of Vector(1)
in 2.13.1 is Vector
Welcome to Scala 2.13.1 (OpenJDK 64-Bit Server VM, Java 1.8.0_202).
Type in expressions for evaluation. Or try :help.
scala> Vector(1).getClass.getCanonicalName
res0: String = scala.collection.immutable.Vector
Conceptually Scala collections differentiate between concrete collection type and implementation subclasses
/** Defines the prefix of this object's `toString` representation.
*
* It is recommended to return the name of the concrete collection type, but
* not implementation subclasses. For example, for `ListMap` this method should
* return `"ListMap"`, not `"Map"` (the supertype) or `"Node"` (an implementation
* subclass).
*
* The default implementation returns "Iterable". It is overridden for the basic
* collection kinds "Seq", "IndexedSeq", "LinearSeq", "Buffer", "Set", "Map",
* "SortedSet", "SortedMap" and "View".
*
* @return a string representation which starts the result of `toString`
* applied to this $coll. By default the string prefix is the
* simple name of the collection class $coll.
*/
protected[this] def className: String = stringPrefix
For example, we refer to Vector1
is an implementation subclass whilst Vector
as a concrete collection class even though Vector
is technically speaking an abstract class.
We can observe implementation subclasses at play for other collection types as well, for example
scala> Set(1).getClass.getCanonicalName
val res1: String = scala.collection.immutable.Set.Set1
Implementation subclasses are usually a private implementation detail:
the concrete runtime class that you get from
Map(...)
ortoMap
is an implementation detail and the vast majority of the time you shouldn't need to worry about it (but when you do, you can check withgetClass
).
Upvotes: 1