Rubyの継承について

#プログラミングの勉強日記
2020年7月11日　Progate Lv.175
RubyⅤ

#継承
　クラスを1から作ることもできるが、すでにあるクラスを利用してそのクラスを元に新しいクラスを作れる。そうすることで共通部分をまとめることができ、効率的にコードが書ける。
　あるクラスをもとにして新たなクラスを作ることを継承という。`class 新しいクラス名 < 元となるクラス名`で他のクラスを継承して新しいクラスを定義することができる。新しいクラスは「子クラス」、元となるクラスは「親クラス」という。
　親クラスのインスタンスメソッドが引き継がれる。

```ruby:food.rb
require "./menu"
class Food < Menu
end
```

子クラスのインスタンスは、継承すると子クラスは親クラスのインスタンスメソッドを引き継ぐ。

```ruby:index.rb
food1=Food.new
puts food1.name
puts food2.info
```

```ruby:menu.rb
class Menu
  attr_accessor :name 
  #処理
  def info
    return "#{self.name} #{self.price}円"
  end
end
```

#インスタンス変数の追加
　子クラスにインスタンス変数を追加するためには今まで通り`attr_accessor`を使う。

```ruby:menu.rb
class Menu
  attr_accessor :name 
  attr_accessor :price
end
```

FoodクラスはMenuクラスを継承しているので。「name, price, calorie」の3つのインスタンス変数を持つ。

```ruby:food.rb
class Food < Menu
  #Foodクラスにcalorieを追加する
  attr_accessor :calorie
end
```

同様にしてインスタンスメソッドも追加することができる。

#オーバーライド
　親にあるメソッドと同じ名前のメソッドを子クラスで定義すると、メソッドを上書きすることができる。このことをオーバーライドという。

```ruby:index.rb(メソッドを呼び出す)
food1~Food.new(...)
food1.calorie=700
puts food1.info
```

```ruby:menu.rb(親クラス)
class Menu
  #処理
  def info
    #処理
  end
end
```

```ruby:food.rb(子クラス)
class Food < Menu
  #処理
  #メソッドの上書き（上書きしたメソッドが呼び出される）
  def info
    #処理
  end
end
```

　子クラスのインスタンスは子クラスで定義したメソッドを優先して呼び出す。よって、子クラスと親クラスに同じ名前のメソッドがある場合は、子クラスのメソッドの内容が上書きされる。initializeメソッドでもオーバーライドができる。

#super 
　オーバーライドしたメソッドの中で`super`とすることで、親クラスの同じ名前のメソッドを呼び出せる。superではメソッドを呼び出しているので、親クラスのメソッドに合わせてsuperに対して引数を渡す必要がある。

```ruby:menu.rb
class Menu
  attr_accessor :name 
  attr_accessor :price
  def initialize(name:, price:)
    self.name=name
    self.price=price
  end
end
```

```ruby:food.js
class Food < Menu
  attr_accessor :calorie
  def initialize(name:, price:, calorie:)
    super(name: name, price: price)
    self.calorie=calorie
  end
end
```

<img width="751" alt="0711.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/4351d5ed-132d-2f4b-6976-eec923c59e07.png">

#Dateクラス
　日付を扱うクラス。DateクラスはRubyがすでに用意しているクラスで、`require`でdateを読み込むことでクラスを定義しなくても使える。<font color=blue>すでに用意されているクラスは他とはrequireの書き方が異なる</font>

```ruby:index.rb
# "/date"ではない！
reruire "date"
```

##Dateクラスのインスタンス
　`Date.new`でインスタンスを生成できる。`Date.today`で今日の日付のインスタンスを作れる。

```ruby:index.rb
require "date"
#引数に「年・月・日」を渡してDateメソッドを作成
date1=Date.new(2020,7,8)
puts date
```
```:コンソール
2020-07-08
```

##Dateクラスのインスタンスメソッド
　多くのインスタンスメソッドがある。日曜日かどうかを真偽値で渡すのは`sunday?`メソッド。

```ruby:index.rb
require "date"
date1=date1.new(2020,7,11)
puts date1.sunday?
```
```:コンソール
false
```

#クラスメソッド
　クラスに対して呼び出すメソッドのこと。`Date.today`の`today`のとこ。クラスメソッドは`def クラス名.メソッド名`とすることで定義できる。インスタンスメソッドと異なり、メソッド名の前にクラス名を書く。
　クラスメソッドの呼び出しは、`クラス名.メソッド名`とする。

```ruby:menu.rb
class Menu
  #処理
  #今日の日付が日曜日かどうかを真偽値で返す
  def Menu.is_discount_day?  
    #今日の日付の情報を持つDateインスタンス
    today=Date.today
    return today.sunday
  end
end
puts Menu.is_discount_day?
```

インスタンスメソッドの中でクラスメソッドを呼び出す

```ruby:menu.rb
class Menu
  #処理
  def get_total_price  #インスタンスメソッド
    if Menu.discount_day?  #クラスメソッドの呼び出し
      #処理
    end
  end
end
```

<img width="711" alt="0711-1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/97bfb510-3de3-9620-c4c0-c737c33988df.png">