- Learn Scala Programming
- Slava Schmidt
- 498字
- 2021-06-10 19:35:45
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 AnyVal, and 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.
- C#高級編程(第10版) C# 6 & .NET Core 1.0 (.NET開發經典名著)
- Visual C++串口通信開發入門與編程實踐
- Photoshop智能手機APP UI設計之道
- MongoDB for Java Developers
- Web Development with Django Cookbook
- 編寫高質量代碼:改善C程序代碼的125個建議
- Quarkus實踐指南:構建新一代的Kubernetes原生Java微服務
- Interactive Applications Using Matplotlib
- Spring快速入門
- 一本書講透Java線程:原理與實踐
- CRYENGINE Game Development Blueprints
- .NET 4.5 Parallel Extensions Cookbook
- Building Dynamics CRM 2015 Dashboards with Power BI
- Web Developer's Reference Guide
- 零基礎學HTML+CSS第2版