Reputation: 21
How are primitive types in Scala objects if we do not use the word "new" to instantiate the instances of those primitives? Programming in Scala by Martin Odersky described the reasoning as some enforcing by a "trick" that makes these value classes to be defined abstract and final, which did not quite make sense to me because how are we able to make an instance of these classes if its abstract? If that same primitive literal is to be stored somewhere let's say into a variable will that make the variable an object?
Upvotes: 2
Views: 1174
Reputation: 3390
I assume that you use scala 2.13 with implementation of literal types. For this explanation you can think of type
and class
as synonyms, but in reality they are different concepts.
To put it all together it worth to treat each primitive type as a set of subtypes each of which representing type of one single literal value.
So literal 1
is a value and type at the same time (instance 1
of type 1
), and it is subtype of value class Int
.
Let's prove that 1
is subtype of Int by using 'implicitly':
implicitly[1 <:< Int] // compiles
The same but using val
:
val one:1 = 1
implicitly[one.type <:< Int] // compiles
So one
is kind of an instance (object) of type 1
(and instance of type Int
at the same time because because Int
is supertype of 1
). You can use this value the same way as any other objects (pass it to function or assign to other vals
etc).
val one:1 = 1
val oneMore: 1 = one
val oneMoreGeneric: Int = one
val oneNew:1 = 1
We can assume that all these vals
contain the same instance of one single object because from practical perspective it doesn't actually matter if this is the same object or not.
Technically it's not an object at all, because primitives came form java (JVM) world where primitives are not objects. They are different kind of entities.
Scala language is trying to unify these two concepts into one (everything is classes), so developers don't have to think too much about differences.
But here are still some differences in a backstage. Each value class is a subtype of AnyVal
, but the rest of the classes are subtype of AnyRef
(regular class).
implicitly[1 <:< AnyVal] //compiles
implicitly[Int <:< AnyVal] // compiles
trait AnyTraint
implicitly[AnyTraint <:< AnyVal] // fails to compail
implicitly[AnyTraint <:< AnyRef] // compiles
And in addition, because of its non-class nature in the JVM, you can't extend value classes
as regular class or use new
to create an instance (because scala compiler emulates new
by itself). That's why from perspective of extending value classes you should think about them as final and from perspective of creating instances manually you should think of them as abstract. But form most of the other perspectives it's like any other regular class.
So scala compiler can kind of extend Int
by 1,2,3 ..
types and create instances of them for vals
, but developers can't do it manually.
Upvotes: 1