第1章:Hello Worldから始めるScala


プログラムは動かさないと始まらない!最初は動かなくて嵌るかもしれない。
でも自分の手を動かして書いたソースが動き始めるともっと書きたくなってくるはず!

手を動かすことに喜びを感じたら、プログラミングの才能があるね!
最初はうまく書けなくても良いんだよ。
とにかくソースを書いて動かしてみようぜ!!

事前準備

まずは動作環境が必要だ。Windows7しか想定してない。すまん。

JavaとScalaのインストール・ダウンロード

以下のバージョンでダウンロードしインストールする。

環境変数の設定

  • JAVA_HOME

    • JAVA_HOME=C:\Program Files\Java\jdk1.7.0_21
  • SCALA_HOME

    • SCALA_HOME=C:\Program Files\scala

以上!

Hello Worldを出力してみる

新しい言語を始める際にまずやることは"Hello World"の出力。
もちろんここでも基本に忠実に"Hello World"をやるよ。

今回の全てのソースのInputとOutput。

  • Input

    • なし
  • Output

    • コンソールに"Hello World"と出力

ソース

HelloWorld.scala
    object HelloWorld{
      def main(args: Array[String]){
        if(args.size == 0) {
          val strs = Array("Hello", "World")
              output(strs)
        } else {
              printf("Invalid args.")
        }
      }

      def output(strs: Array[String]):Unit = {
        for(str <- strs) {
          printf("%s ", str)
        }
      }
    }

上記を"HelloWorld.scala"というファイル名で保存だ。
そしてコンソールでscala HelloWorld.scalaとコマンドを叩こう。

"Hello World"が出力されるよ!

    $ scala HelloWorld.scala
    Hello World

ソースの説明

動いたらどうなっているか気になってこないかな?
ここから説明するよ!!

objectキーワード

シングルトンオブジェクトの定義。Javaとは違い静的(static)な扱いがない。

Scalaの世界では全てがオブジェクトとなる。

複数のインスタンスを必要としない場合に使用する。

シングルトンオブジェクトとは、インスタンスが1つしか存在しない
オブジェクトのことである。

例えば今回のソースのように、実行の起点となるmainメソッドには
複数のインスタンスは必要ない。そのためobject HelloWorld
宣言することにより、HelloWorldシングルトンオブジェクトの
mainメソッドという形にしている。

代表的なキーワード

  • case
  • class
  • match
  • return
  • trait

mainメソッド

objectキーワードで記述したが、実行の起点となるメソッド。
scalaのソースを動かしたい場合に使用する。通常は以下の構文となる。

    object オブジェクト{
      def main(args: Array[String]): Unit = {
        処理
      }
    }

: Unit =は省略可能である。Unitとは戻り値がない場合の宣言。
Javaではvoidにあたる。

オブジェクトとクラス、インスタンス、フィールド、メソッド

オブジェクト指向の核となる概念。Javaの世界では以下のように考える。

  • クラス = 型。class宣言する。
  • インスタンス = 型を具現化したモノ。newする。newする毎にメモリが確保される。
  • オブジェクト = クラスでありインスタンスでもある。ソース上ではObjectクラス以外、明示的なオブジェクトは現れない。
  • フィールド = 状態を表す。インスタンス毎に値が変わることが多い。
  • メソッド = 処理。何をするかを記述する。

言葉だけじゃわかりにくいから図を作ってみた。
車で考えてみるよ。

クラスは だ。車には色んな属性があるけど、今回は 車種 だけとする。
これがフィールドだ。
では車種を決めてみよ。例えば バススポーツカー にしてみるよ。
するとインスタンスができるんだ。

車ができること、例えば 走る だ。これがメソッド。
インスタンス化したバス・スポーツカーももちろん 走る ことができる。
違いはないかもしれないし、速さに違いがあるかもしれない。

どうわかったかな?
ところでオブジェクトはって?
オブジェクトは であり、 バス であり スポーツカー であるんだよ。

if文

分岐を表す。条件はtrue, falseで評価する。

    if(args.size == 0) {
      val strs = Array("Hello", "World")
        output(strs)
      } else {
        printf("Invalid args.")
    }

上記では、条件args.size == 0を評価し、trueの場合は直後の{}内の処理を実行する。
falseの場合はelse直後の{}内の処理を実施する。

ここでargs.sizeは配列argsのサイズである。

defキーワード、for式、printf関数

   def output(strs: Array[String]):Unit = {
     for(str <- strs) {
       printf("%s ", str)
     }
   }

defキーワード

メソッド宣言。下記の構文が通常の形となる。

    def メソッド名(引数リスト): メソッドの戻り値の型 = {}

for式

繰り返しを表す。

このfor式は、文字列配列から1要素ずつ順番に抜き出し、
printfの引数としている。<-はジェネレータと呼ぶ。

printf関数

フォーマットを指定し文字列を出力する。第1引数の%s%sを、
第2引数の値で置換して出力する。

valキーワード

イミュータブル(値を変えることができない)変数を定義する。

    val strs = Array("Hello", "World")

上記のように変数strsに一度値(配列)を設定すると、
strsに別の値を入れ直すことはできない。Javaのfinalと同等。

Scalaらしくリファクタリング

HelloWorld.scalaはJavaのソースとほとんど変わらないので、
outputメソッドをもう少しScalaらしくしてみたから確認してみよう!
これでもOutputは変わらないでしょ?

リファクタリング後のソース

HelloWorld1.scala
    object HelloWorld{
      def main(args: Array[String]){
        if(args.size == 0) {
          val strs = Array("Hello", "World")
          output(strs)
        } else {
          printf("Invalid args.")
        }
      }

      def output(strs: Array[String]){
        strs.foreach(printf("%s ", _))
      }
    }

変更点の説明

細かい変更は自分で確認してね!大きな変更点だけ書くよ。

foreachキーワード

これも繰り返しを表す。引数に関数を渡すことができる。

    def output(strs: Array[String]){
      strs.foreach(printf("%s ", _))
    }

ここでは、printf("%s ", _)という関数を引数として渡している。
プレイスホルダー_が配列strsの要素を表す。

配列strsから1要素ずつ取り出すたびにプレイスホルダー_
要素の値を設定し、引数の関数を呼び出す。

まとめ

基本のHelloWorldだけど、キーワードを何個か入れ込んだから、
盛り沢山だったかな。このソースをいじって色々試してみようぜ!

今回のサンプルソースを通しScalaのソースを実際に動かすことで、

体で感じてくれたかな?