第4章：But I remember オブジェクト指向

今回はオブジェクト指向を試してみるよ！

Scalaはオブジェクト指向もできるんだ！
ソースでの話がメインだよ。
だからオブジェクト指向プログラミングだ。

Javaだと冗長だけど、Scalaだとコンストラクタ・フィールドの
組み合わせで凄いシンプルになるんだ。

JavaBeans、いわゆる情報格納役で見てみよう。

# Javaのソースコード
```java:User.java
public class User {

	private final long id;

	private final String firstname;

	private final String lastname;

	public User(long id, String firstname, String lastname) {
		this.id = id;
		this.firstname = firstname;
		this.lastname = lastname;
	}

	public long getId() {
		return id;
	}

	public String getFirstname() {
		return firstname;
	}

	public String getLastname() {
		return lastname;
	}

	public String getFullname() {
		return this.firstname + " " + this.lastname;
	}
}
```
Javaプログラマーから見ると、普通のソースだと思う。
説明は省くよ！これをScalaにしてみよう。


# Scalaのソースコード
```scala:User.scala
class User(val id: Long, val firstname: String, val lastname: String) {
  def getFullname() = this.firstname + " " +  this.lastname
}
```
なんということでしょう！
Javaだとダラダラ長かったソースが、わずか3行になってしまった。


## クラスの書き方
- クラス名は、`class`の後に書くんだ！
- 引数は、クラス名の次に書くんだ！
- メソッドは、`{...}`の中に`def`で書くんだ！。

あれ？コンストラクタ宣言は？フィールド宣言は？

## 基本コンストラクタ
Scalaではクラス全体が__基本コンストラクタ__というモノになる。
つまりコンストラクタはもう宣言してあるんだ。

## フィールド宣言
基本コンストラクタの引数に、`val`(または`var`)を付ければ
そのままフィールドになる。

だからJavaでは長かったUserクラスが、Scalaでは3行で実現できたんだ。

## フィールドへのアクセス
インスタンス.フィールドで可能だ！

    val user = new User(1, "源次", "富樫")
    user.firstname

直接フィールドにアクセスするのって、カプセル化の観点からいけないのでは？って。
確かにそうなんです。。。
今回はフィールドを`val`にしているということで、許して下さい。

もちろん、フィールドに直接アクセスできないようにすることも可能だよ。

```scala:User1.scala
class User(private val id: Long, private val firstname: String, private val lastname: String) {
  def getFullname() = this.firstname + " " +  this.lastname
}

val user = new User(1, "源次", "富樫")
println(user.id)
```

引数の型の前に、`private`を宣言した。

これを実行すると、

    $ scala User1.scala
    User1.scala:6: error: value id in class User cannot be accessed in this.User
    println(user.id)
                 ^
    one error found

となり。外からは`id`フィールドにアクセスできないというエラーが出るよ。

これで`getter`を用意すれば、フィールドに直接アクセスしないで
フィールドの値を取得できるね！


次にこのソースを少し変えてみよう！

# 改変したScalaのソース

```scala:User2.scala
class User(val id: Long, val firstname: String, val lastname: String, val fullname:Fullname = new Fullname) {
  def getFullname() = this.fullname.get(firstname, lastname)
}

class Fullname() {
  def get(firstname: String, lastname: String) = firstname + " " + lastname
}

class FullnameInJapan() extends Fullname {
  override def get(firstname: String, lastname: String) = lastname + " " + firstname
}

val user1 = new User(1, "源次", "富樫", new FullnameInJapan)
println(user1.getFullname())

val user2 = new User(2, "鯛雄", "松尾")
println(user2.getFullname())
```

今度は実行できるようにしてあるので、実行してみよう！

    $ scala User2.scala
    富樫 源次
    鯛雄 松尾

出力結果だけど、`user1`と`user2`で`firstname`、`lastname`の順番が違っているよね。

## コンストラクタのデフォルト値
Userクラスのコンストラクタを先程とは少し変えているよ。わかるかな？

    class User(val id: Long, val firstname: String, val lastname: String, val fullname:Fullname = new Fullname) {
      def getFullname() = this.fullname.get(firstname, lastname)
    }

`fullname`という引数を増やしているよ。型は`Fullname`だ。

そして` = new Fullname`ってあるよね？これがコンストラクタのデフォルト値だ。
このデフォルト値は、`fullname`が指定されない場合に使用する。

    val user2 = new User(2, "鯛雄", "松尾")

これがデフォルト値を使う場合だね。

ところでこの`fullname`は何に使われるかと言うと、
メソッド`getFullname`の処理として呼び出されるのだ。

オブジェクト指向的に言うと、フルネームを作成するための処理を委譲しているのだ。
これでちょっとオブジェクト指向ぽくなったんじゃない？

オブジェクト指向プログラミングでは使われる頻度が多い、
__Strategyパターン__ぽくしてみたよ。

## クラスの拡張
クラス`Fullname`は次のようになっている。

    class Fullname() {
      def get(firstname: String, lastname: String) = firstname + " " + lastname
    }

そして、クラス`Fullname`を__拡張__してクラス`FullnameInJapan`を定義している。

    class FullnameInJapan() extends Fullname {
      override def get(firstname: String, lastname: String) = lastname + " " + firstname
    }

`extends`で拡張し、`overrid`でメソッドを__オーバーライド__する。
Javaとそんなに変わらないんだ。

クラス`FullnameInJapan`を使う場合は、以下のようになる。

    val user1 = new User(1, "源次", "富樫", new FullnameInJapan)

これで、`fullname`のデフォルト値を使わなくなる。

# まとめ
今回はオブジェクト指向の中で、コンストラクタとフィールドに注力してみた。

Scalaでは冗長な部分を排除でき、単純に記述量が減り見通しが良くなることを
__体で感じてくれたかな？__


今回で、第一部を完了して、次章からScalaの世界で泳ぎ始めるよ！