水島宏太
 筑波大学第三学群情報学類を卒業したのち,現在は,筑波大学大学院システム情報工学研究科コンピュータサイエンス専攻博士後期課程1年。プログラミング言語や処理系に強い興味を持っている。現在の研究テーマは,プログラミング言語の構文解析アルゴリズム。Scala勉強会を不定期で行うなど,研究の合間にScalaの普及活動を行っている。

 前回まで羽生田さんによるScalaの文法的な特徴の紹介がありましたが,今回はゲストということで,Scalaの型システムの概要やそれに関連した機能を紹介します。特にScalaのクラス階層とJavaのクラス階層の違い,Genericsの共変と反変,Existential Type,Structural Type,Compound Typeについて紹介します。

Javaとの類似点

 Scalaの型システムの基本的な部分はJavaと非常に類似しています。ScalaはJavaと同様に単一のルートクラスを持っていますし,Javaにインタフェースの多重継承があるのと同様に,Scalaではtraitを多重継承することができます(traitは実装を持てるため,Javaのインタフェースとはもちろん異なりますが,traitはそれ自体で型としての機能も持っているため,実装を持たないtraitはJavaのインタフェースと同じようにみなすことができます)。

 しかし,いくつかの点でJavaとは異なる部分と,Javaに比べて追加された機能があります。この記事の以降の部分では,主にJavaと異なる点や追加された機能に重点を置いてScalaの型システムについて説明します。

Scalaのクラス階層(1) - Any, AnyVal, AnyRef

 連載第4回でも簡単に説明がありましたが,Scalaのクラス階層はJavaのそれと似通っています。まず,単一のルートクラスであるAnyが存在しており,Scalaにおけるすべての型は直接・間接にAnyを継承しています。これは,Javaの参照型におけるルートクラスがjava.lang.Objectであることに似ています。

 一方で,Javaとは異なった部分もあります。まず,ScalaにはJavaのようなプリミティブ型は存在しません。では,どうなっているのかというと,Javaのプリミティブ型に相当するすべての型はクラスとなっており,かつ,Anyを継承したAnyValのサブクラスになっているのです。

 また,すべての参照型はAnyRefの直接または間接のサブクラスになっています。先ほど,Anyがjava.lang.Objectに似ているということを書きましたが,実際の意味付けを考えると,AnyRefがjava.lang.Objectに対応していると言うほうが正確です(図1)。

図1●Scalaのクラス階層(1)
図1●Scalaのクラス階層(1)

 ところで,本題からはずれますが,プリミティブ型に相当するクラスで,整数(Byte,Short,Char,Int,Long)や浮動小数点を表す(Float,Double)クラスが親子関係ではなく兄弟関係にあるのを見て,「ByteからIntなど,Javaなら暗黙に変換してくれる場合まで,Scalaだといちいち明示的に変換しなければいけないのか。面倒くさい」というような感想を持たれた方も居るのではないでしょうか。

 実は,Scalaではimplicit conversionという,暗黙の型変換をユーザーが定義できる機能が備わっており,標準ライブラリにおいて,ByteからInt,ShortからIntなど,Javaなら暗黙の内に型変換してくれるような場合において,同様の挙動をしてくれるようにimplicit conversionが定義されています。このimplicit conversionという機能は非常に興味深い機能なので,連載の後のほうで説明があるかもしれません。

Scalaのクラス階層(2) - Nothing, Null

 Scalaのクラス階層には,Javaと異なり,bottomと言うべき型が存在します。それがNothingです。Nothingはすべての型のサブタイプである,つまりNothing型であればどんな型の変数にでも代入できるような特殊な型で,Nothing型の値は存在しません。

 値を持たない型など何の意味があるのかと思われるかもしれません。しかし,Nothing型は,絶対にreturnしない関数の返り値の型や,後述するGenericsにおいて,空のコレクションの要素型を表すためなど,Scalaにおいて重要な役割を持っています。

 また,すべての参照型(AnyRef)のサブタイプである,つまりすべての参照型の変数に代入できるNull型が存在します。Null型の値はnullリテラルのみです(実は,Javaでもnull型があり,ScalaにおけるNull型と似た役割を担っているのですが,Scalaと違い,Javaではnull型を明示的に書く手段が存在しないため,意識する機会はほとんど無いでしょう)。

 これらの関係を図にすると,図2のようになります。

図2●Scalaのクラス階層(2)
図2●Scalaのクラス階層(2)