Scala's types hierarchy and special types

Type constraints in combination with Scala's type hierarchy give us a few interesting classes that are important to know about. To recap, the type hierarchy is represented in the following diagram:

In Scala, all types have a maximum upper bound of Any and a lower bound of Nothing.

Value Classes is a Scala way to avoid allocating runtime objects. This works by wrapping JVM's primitive types. Scala already represents numeric types and Boolean and Char as AnyValand it is possible to implement custom value classes by extending AnyVal and obeying a few restrictions. An interesting subtype of AnyVal is a Unit type, which represents a case where something unimportant needs to be returned from a function or a method. It roughly corresponds to the void return type and has a single member, ().

AnyRef is a representation of any type that is allocated at runtime. In JVM, it is possible to have null in a place where an object reference is expected; the type of null is Null. The Null type has a single inhabitant, null, the same way Unit has a single value of ().

Nothing is a special subtype of every other type and has no members. Because of this, it is not possible to instantiate members of that type. As a result, it is useful to indicate that the only possibility for a method or function to terminate is to do this abnormally, usually by throwing an exception.

There are two traits that are not represented in the preceding diagram, Serializable and Product. The former marker trait is used to tell the JVM that some class should be serializable across platforms, and it just delegates to Java's interface, java.io.Serializable

The Product stays for the Cartesian product, which is basically just an ordered set of pairs of named types. In Scala, Product is extended by tuples and case classes.

The Self type is another special notion in Scala that's used to define dependencies between traits without declaring an extension relation. This syntax allows you to bring in the scope of the trait members from other traits, as shown in the following code:

trait A { def a: String }
trait B { def b: String }
trait C { this: A => // override `this`
def c = this.a
}
trait D { self: A with B => // any alias is allowed; mixed traits
def d = this.a + this.b
}

The last member in our zoo of special types is Dynamic. This is a marker trait that allows you to use the dynamic invocation of methods (also known as duck typing).

It feels a bit inappropriate to go into the details of Dynamic here because Scala's strength is exactly the opposite—to express knowledge about the system statically using proper types. For curious readers, official documentation on this is available here: https://www.scala-lang.org/api/current/scala/Dynamic.html

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.12.153.212