Scalaの特徴を紹介し、基本構文や関数、クラスなど、Scalaの基本的な機能について解説する入門連載
前回の連載第1回記事「EclipseでScalaプログラミングを始めるための基礎」では、Scalaの特徴についての解説から始まり、Scalaのインストール、そしてScalaプログラムを記述してREPLとScala IDE for Eclipse(以下、Scala IDE)での動作を確認してみました。Scalaプログラミングを始めるための準備ができたので、いよいよ今回からScalaの文法について紹介します。
第1回記事では、Scala標準のREPLとScala IDEで動作を確認してみました。今後本記事のサンプルコードは、どちらで確認しても問題はありませんが、対話的に実行でき、1文ごとにコードの結果が分かって便利なので、基本的にはREPLを用いて説明していきます。
Scala IDEを使用する場合、第1回記事の『Scala IDE for Eclipseで「Hello Scala!」』を参照してプロジェクトを作成して実行してください。REPLを使用する場合は、コンソール上でscalaコマンドを実行し、REPLを起動してください。
Scalaには、何度でも代入が可能な変数(var)と初期化した後に代入ができない定数(val)があります。変数(var)はJavaでいう通常の「変数」と変わりません。定数(val)はJavaでいう「final変数/フィールド」と同じです。
まずは、変数(var)を使ってみましょう。宣言する形式は、以下2つのいずれかにします。
var 変数名:型 = 初期値
var 変数名 = 初期値
また、以下のようにすれば、複数の変数を一度に定義できます。
var 変数名1,変数名2 = 初期値
scala> var num:Int = 10 num: Int = 10 scala> num = 20 num: Int = 20 scala> var n1,n2,n3 = 1 n1: Int = 1 n2: Int = 1 n3: Int = 1
次に定数(val)を使用してみましょう。宣言する形式は、先ほどのvarがvalになっただけです。ここでも、初期化後に再度、代入してみます。
scala> val message = "Hello" message: java.lang.String = Hello scala> message = "Scala" <console>:8: error: reassignment to val message = "Scala"
valで宣言されているので、再代入ができずにエラーが発生します。今後の連載で紹介しますが、関数型プログラミングをしていくうえで一度値を決めたら変更できないvalというものは重要です。現状では、変数はまずvalで宣言し、valではうまくいかなかったり冗長になってしまう場合のみ、varを使用するようにしてみてください。
また、messageを宣言している部分では型を指定していません。それにもかかわらず、「"Hello"」で初期化した段階でmessageの型が「java.lang.String」であると判断されています。
これがScalaの持つ機能「型推論」です。このように、Scalaが型を推論できるときはScalaに任せた方が簡潔なコードが書けますが、明示的に型の宣言をした方がよい場合もあります。
型宣言をすることでコードが予期しない型推論を防げますし、後でコードを読んだときに分かりやすいというメリットもあります。状況に応じて使い分けてください。
前回のサンプルコードを見ても分かりますが、Scalaで書いたコードにはセミコロンがありません。Javaなどと同じようにセミコロンを使用することも可能ですが、通常は1行に複数の文を記述したいとき以外、あまりセミコロンを使用することはありません。
Scalaの基本データ型は、Javaのそれと同じ意味を持ちます。表1がScalaの基本データ型です。Stringを除けば、Javaのプリミティブ型(具体的な値を格納するための型)の先頭文字を大文字にしたものになっています。
型名 | 説明 | デフォルト値 |
---|---|---|
Byte | 8ビット符号付き整数 | 0 |
Short | 8ビット符号付き整数 | 0 |
Int | 32ビット符号付き整数 | 0 |
Long | 64ビット符号付き整数 | 0 |
Char | 16ビット符号なしUnicode文字 | '\0' |
String | Charシーケンス | null |
Float | 32ビットIEEE754単精度浮動小数点数 | 0.0 |
Double | 64ビットIEEE754単精度浮動小数点数 | 0.0 |
Boolean | trueかfalse | false |
表1 Scalaの基本データ型 |
「デフォルト値」というのは、varで変数を宣言したときに「_」(アンダースコア)を指定した場合の値です。宣言した時点で値が定まっていない場合、「_」で取りあえず変数を宣言しておき、後で代入できます。
scala> var longNumber:Long = _ longNumber: Long = 0
ScalaとJavaの基本データ型における違いとしては、「Scalaにはプリミティブ型がなく、すべてオブジェクト型である」という点が挙げられます。オブジェクトなので、基本データ型の変数や数値に対してもメソッドを呼べます。
scala> var num:Int = 10 num: Int = 10 scala> num.toString res0: java.lang.String = 10 scala> 10.toString res1: java.lang.String = 10
基本データ型の中で、Stringだけは「java.lang」パッケージに属しており、それ以外は「scala」パッケージに属しています。
Scalaでは、scalaパッケージとjava.langパッケージが自動的にimportされるので、そのまま使えます(※Scalaのパッケージやimportについては次回以降で紹介する予定です)。
先に述べた基本データ型は、リテラル(コードに値を直接記述する書き方)として書けます。基本的なリテラルを順番に紹介していきましょう。
整数リテラルは10進数、8進数、16進数で表現できます。
種類 | フォーマット | 例 |
---|---|---|
10進数 | 0か0以外の数字に0個以上の数字が続く | 0、1、765 |
8進数 | 0の後に1個以上の数字(0〜7)が続く | 011、046 |
16進数 | 0xの後に1個以上の16進数数値(0〜9、A〜F、a〜f)が続く | 0xFF、0x3B |
表2 整数リテラル |
有効な値は、代入する値の型によって決まります。表3が整数リテラルの範囲です。なお、Longリテラルには値の末尾に「L」か「l」を付ける必要があります。
型名 | 最小値 | 最大値 |
---|---|---|
Byte | -2^7 | 2^7-1 |
Short | -2^15 | 2^15-1 |
Int | -2^31 | 2^31-1 |
Long | -2^63 | 2^63-1 |
Char | 0 | 2^16-1 |
表3 整数リテラルの最小値と最大値 |
0の後に「.」(ピリオド)が付き、その後に0個以上の数値が続くと、「浮動小数点リテラル」です。「Floatリテラル」の場合は末尾に「F」か「f」がつきます。そうでなければ、「Doubleリテラル」と見なされます。
Doubleの場合は、末尾に「D」か「d」を付けられます。また、指数表現を付加できます。指数の形式は、「e」または「E」の後に「+」か「-」と1個以上の数値が続きます。
scala> val float = 0.1 float: Double = 0.1 scala> val float = 0.1F float: Float = 0.1 scala> val double = 0.1e+3f double: Float = 100.0
次は、ブールリテラルです。これはBoolean型に代入できる値です。trueかfalseを代入できます。
scala> val t = true t: Boolean = true scala> val f = false f: Boolean = false
文字リテラルは、基本的には「'」(シングルクオート)で囲まれたUnicode文字かエスケープシーケンスです。明示的な文字か、「\u」に続いて4個の16進数値を並べたUnicode文字の一般表現、または、「\」に続いて文字のコードポイントを8進数か16進数で表明した値を書けます。
scala> val a = 'A' a: Char = A scala> val b = '\u0041' b: Char = A scala> val c = '\101' c: Char = A
そして、有効なエスケープシーケンス文字があります。
リテラル | 意味 |
---|---|
\n | 改行 |
\r | 復帰 |
\t | タブ |
\b | バックスペース |
\" | ダブルクオート |
\' | シングルクオート |
\\ | バックスラッシュ |
\f | 改ページ |
表4 特別なエスケープシーケンスの文字リテラル |
「"」(ダブルクオート)で文字を囲むと、文字列リテラルになります。内容は文字リテラルと同じで、有効なエスケープシーケンスもあります。なお、生成される文字列はJavaのString型です。
scala> val s = "hello" s: java.lang.String = hello scala> val es = "\"\'\\" es: java.lang.String = "'\
また、「"""」(ダブルクオート3つ)を使用して文字列を囲むと、「生の文字列(raw string)」を使えます。これは文字列内のエスケープシーケンスを無視し、改行などもそのまま記述できます。
scala> val es = """\"\'\\""" es: java.lang.String = \"\'\\
文字列に多くのエスケープシーケンスが含まれる場合、raw stringを使用すると分かりやすく記述できます。
シンボルリテラルは「'」(シングルクオート)を名前の前に付けることで、その名前を表すSymbolリテラルとなります。これは「scala.Symbol」のインスタンスで、「'symbol」というリテラルは、「scala.Symbol("symbol")」という式と同じ意味です。
なお、同じ名前を持った2つのシンボルは、同じオブジェクトを示します。そのため、マップのキーとして文字列の代わりにSymbolを使うことがあります。
scala> val s = 'sSymbol s: Symbol = 'sSymbol scala> s.name res4: String = sSymbol
以上が一般的なリテラルです。ここまでは、基本データ型と一般的なリテラルについてご紹介しました。次ページでは、Scalaの配列型について見てみましょう。
Copyright © ITmedia, Inc. All Rights Reserved.