【初心者向け・動画付き】たい焼きクラスで学ぶ、楽しいオブジェクト指向プログラミング入門


## はじめに

先日、こちらのQiita記事を拝見しました。

[クラスとオブジェクトの関係性 \- Qiita](https://qiita.com/daisakuhazui/items/920bca4fe1ad28c77cef)

この記事では「たい焼きの型」をクラスと見なして、クラスとオブジェクトの違いを説明しています。
ただ、着眼点は良かったのですが、記事の中で使われているサンプルコードが少しオブジェクト指向プログラミングの面白さを伝え切れていないように感じました。

そこでこの記事では「たい焼き」をお題にして、オブジェクト指向プログラミングの考え方（というか、面白さ）を簡単に説明していきます。

## 動画がメインです！

この記事の内容はYouTubeで解説しています。
というか、動画の方がメインで、この記事はオマケです。
ぜひ最初に動画の方をチェックしてください！

[【初心者向け】たい焼きクラスで学ぶ、楽しいオブジェクト指向プログラミング入門 \- YouTube![Screen Shot 2017-09-30 at 10.38.23.png](https://qiita-image-store.s3.amazonaws.com/0/7465/ed94ea59-f832-6484-4d4d-cf21cc37bd86.png "Screen Shot 2017-09-30 at 10.38.23.png")](https://www.youtube.com/watch?v=HsivL1JBRaw&feature=youtu.be)


ちなみに、動画の長さは30分ちょっとあるので、1.5倍速ぐらいで見ることをオススメします。

## コードはGitHubに置いています

ソースコードはGitHubに置いてあるので、必要に応じてこちらも参照してください。

[JunichiIto/taiyaki\-sandbox: Sample app for object oriented programming](https://github.com/JunichiIto/taiyaki-sandbox)

## Minitestで動作確認しています

動画を見てもらうとわかると思いますが、作成したコードはMinitestを使って動作確認しています。
あまり難しいことはやっていないと思いますが、何をやってるのかようわからん、という方はこちらの記事を参考にしてみてください。
（test-unitの話がメインですが、記事の後半にMinitestの話も出てきます）

[Ruby標準のテスティングフレームワークで手軽にテストコードを書く方法 \- Qiita](https://qiita.com/jnchito/items/ff4f7a23addbd8dbc460)

## 本物のたい焼きをイメージしながらコードを書いていきます

動画の中ではこちらのWebサイトを見ながら、「本物のたい焼き」をイメージしています。
（ただし、このサイトの情報どおりに実装しているわけではありません）

[薄焼たい焼　銀のあん](http://www.ginnoan.com/contents/menu/index.html)

![Screen Shot 2017-09-30 at 10.13.29.png](https://qiita-image-store.s3.amazonaws.com/0/7465/9aed4aeb-3153-066a-6284-a3eadd2dd5e8.png "Screen Shot 2017-09-30 at 10.13.29.png")

「本物のたい焼きはどんな状態を持つか？」ということを考えながらTaiyakiクラスを実装していくと、よりいっそう楽しくオブジェクト指向プログラミングができるできるはずです！

## Step 0. Taiyakiクラスを定義する

何はともあれ、Taiyakiクラスを定義してあげましょう。
中身はこれから実装していきます。

```ruby
class Taiyaki
end
```

## Step 1. 「あんこ」の種類を保持できるようにする

Taiyakiクラスにインスタンス変数の`@anko`を追加し、「あんこ」の種類を保持できるようにします。

ここでは以下の2種類を想定します。

- あずき
- 白あん

```ruby
require 'minitest/autorun'

class Taiyaki
  attr_reader :anko

  def initialize(anko)
    @anko = anko
  end
end

class TaiyakiTest < Minitest::Test
  def test_taiyaki
    taiyaki_1 = Taiyaki.new('あずき')
    assert_equal 'あずき', taiyaki_1.anko

    taiyaki_2 = Taiyaki.new('白あん')
    assert_equal '白あん', taiyaki_2.anko
  end
end
```

## Step 2. 「大きさ」を保持できるようにする

Taiyakiクラスにインスタンス変数の`@size`を追加し、「大きさ」を保持できるようにします。

ここでは以下の2種類を想定します。

- ふつう
- 大きめ

```ruby
require 'minitest/autorun'

class Taiyaki
  attr_reader :anko, :size

  def initialize(anko, size)
    @anko = anko
    @size = size
  end
end

class TaiyakiTest < Minitest::Test
  def test_taiyaki
    taiyaki_1 = Taiyaki.new('あずき', 'ふつう')
    assert_equal 'あずき', taiyaki_1.anko
    assert_equal 'ふつう', taiyaki_1.size
    
    taiyaki_2 = Taiyaki.new('白あん', '大きめ')
    assert_equal '白あん', taiyaki_2.anko
    assert_equal '大きめ', taiyaki_2.size
  end
end
```

## Step 3. 自分の状態を文字列として返せるようにする

たい焼きに保持されているあんことサイズを文字列として返せるように、`to_s`メソッドを実装（オーバーライド）します。

```ruby
require 'minitest/autorun'

class Taiyaki
  attr_reader :anko, :size

  def initialize(anko, size)
    @anko = anko
    @size = size
  end

  def to_s
    "あんこ: #{anko}, 大きさ: #{size}"
  end
end

class TaiyakiTest < Minitest::Test
  def test_taiyaki
    taiyaki_1 = Taiyaki.new('あずき', 'ふつう')
    assert_equal 'あずき', taiyaki_1.anko
    assert_equal 'ふつう', taiyaki_1.size
    assert_equal 'あんこ: あずき, 大きさ: ふつう', taiyaki_1.to_s

    taiyaki_2 = Taiyaki.new('白あん', '大きめ')
    assert_equal '白あん', taiyaki_2.anko
    assert_equal '大きめ', taiyaki_2.size
    assert_equal 'あんこ: 白あん, 大きさ: 大きめ', taiyaki_2.to_s
  end
end
```


## Step 4. 「値段」を計算できるようにする

ここでは以下のルールで値段を計算します。

- ベースとなる値段は100円
- 白あんを選ぶと30円プラス
- 大きめを選ぶと50円プラス

上のルールに従って値段を返せるように、Taiyakiクラスに`price`メソッドを追加します。
また、`to_s`メソッドにも値段を出力するようにします。

```ruby
require 'minitest/autorun'

class Taiyaki
  attr_reader :anko, :size

  def initialize(anko, size)
    @anko = anko
    @size = size
  end

  def price
    amount = 100
    if anko == '白あん'
      amount += 30
    end
    if size == '大きめ'
      amount += 50
    end
    amount
  end

  def to_s
    "あんこ: #{anko}, 大きさ: #{size}, #{price}円"
  end
end

class TaiyakiTest < Minitest::Test
  def test_taiyaki
    taiyaki_1 = Taiyaki.new('あずき', 'ふつう')
    assert_equal 'あずき', taiyaki_1.anko
    assert_equal 'ふつう', taiyaki_1.size
    assert_equal 100, taiyaki_1.price
    assert_equal 'あんこ: あずき, 大きさ: ふつう, 100円', taiyaki_1.to_s

    taiyaki_2 = Taiyaki.new('白あん', '大きめ')
    assert_equal '白あん', taiyaki_2.anko
    assert_equal '大きめ', taiyaki_2.size
    assert_equal 180, taiyaki_2.price
    assert_equal 'あんこ: 白あん, 大きさ: 大きめ, 180円', taiyaki_2.to_s

    taiyaki_3 = Taiyaki.new('あずき', '大きめ')
    assert_equal 150, taiyaki_3.price
  end
end
```

## Step 5. 「賞味期限」を管理できるようにする

ここでは製造日の3日後を賞味期限に設定します。
これに伴い、以下のインスタンスメソッドを追加します。

- `produced_on` 製造日（システム日付）を返す
- `expire_on` 賞味期限（製造日の3日後）を返す
- `expired?` 賞味期限が過ぎていれば`true`、そうでなければ`false`

```ruby
require 'minitest/autorun'
require 'date'

class Taiyaki
  attr_reader :anko, :size, :produced_on

  def initialize(anko, size)
    @anko = anko
    @size = size
    @produced_on = Date.today
  end
  
  # 省略

  def expire_on
    produced_on + 3
  end

  def expired?(today = Date.today)
    expire_on < today
  end
  
  # 省略
end

class TaiyakiTest < Minitest::Test
  # 省略

  def test_expired
    taiyaki = Taiyaki.new('あずき', 'ふつう')

    # 製造日 = システム日付
    assert_equal Date.today, taiyaki.produced_on

    # 賞味期限 = 製造日 + 3日
    assert_equal (Date.today + 3), taiyaki.expire_on

    # 当日なら食べられる
    refute taiyaki.expired?

    # 3日目まで食べられる
    refute taiyaki.expired?(Date.today + 3)

    # 4日目を過ぎると食べられない
    assert taiyaki.expired?(Date.today + 4)
  end
end
```

まだまだ「たい焼きクラス」で遊べそうな気がしますが、この例題はこれでおしまいです。

## まとめ

というわけで、この記事では「たい焼きクラス」を使ってオブジェクト指向プログラミングの考え方を簡単に説明してみました。

このように、オブジェクト指向プログラミングではクラスを定義し、その中にデータ（インスタンス変数）とメソッドを持たせることで、実在する物（オブジェクト）に近い形でプログラミングをすることができます。

とりあえず、この記事ではあまり難しいことを言うつもりはありません。
今までクラスやオブジェクトと言われてもピンと来なかった人が、この記事（と動画）を見て、「へ～、オブジェクト指向プログラミングってなんか面白い」と思ってもらえればそれでOKです。

詳しい話は後述する参考文献などで勉強してみてください。

## 参考文献

[オブジェクト指向設計実践ガイド ~Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方](http://amzn.to/2hD8dg2)

オブジェクト指向設計やオブジェクト指向プログラミングを本格的に学びたい！というRubyプログラマの人にはこちらの本がオススメです。

[プロを目指す人のためのRuby入門（2017年11月発売）](http://blog.jnito.com/entry/2017/05/30/120148)

僕（伊藤淳一）が現在制作中のRubyの入門書です。
この本の中でもRubyにおけるオブジェクト指向プログラミングの考え方をあれこれ説明しています。

[オブジェクト指向関連書籍リスト \- give IT a try](http://blog.jnito.com/entry/20100503/1272838579)

僕がその昔読んだオブジェクト指向関連の書籍一覧です。
ただ、記事を書いたのがかなり前なので、絶版になっている本も多いかもしれません。