KOD
KOD

Reputation: 21

How are primitives types objects in Scala?

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

Answers (1)

Bogdan Vakulenko
Bogdan Vakulenko

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

Related Questions