【Ruby】クラスとインスタンス

# 記事概要
クラスとインスタンスについて、まとめる。

# 目的
既存でRubyに定義されている値以外にも、自分で新しい種類の値を作る

# 用語
## クラス
値の元となるものであり、値の共通ルールを定義する
ルールを定義するだけなので、実体がない

## インスタンス
クラスを元にして作られるデータのこと

## イメージ
[![Image from Gyazo](https://i.gyazo.com/8dcddb0c36a642502b782f8b6c537bda.png)](https://gyazo.com/8dcddb0c36a642502b782f8b6c537bda)

## 属性
データの性質となる情報のこと

## 属性値
属性にに当てはまる値のこと

## イメージ
[![Image from Gyazo](https://i.gyazo.com/d3930dce72e97163d418c6af01015683.png)](https://gyazo.com/d3930dce72e97163d418c6af01015683)

# 処理
## クラスの定義
```ruby
class クラス名 # クラス名は半角英大文字
  # 変数やメソッドの定義
end

# Carクラスを定義
class Car
end
```
## クラスメソッド
クラスが使用できるメソッドであり、クラスで共通の処理を行う

### クラスメソッドの定義
```ruby
class クラス名
  def self.クラスメソッド名
    # 処理
  end
end
```

### クラスメソッドの呼び出し
```ruby
クラス名.クラスメソッド名(引数)

# Carクラスを定義
irb(main):001* class Car
irb(main):002*   def self.run
irb(main):003*     puts '走行します'
irb(main):004*   end
irb(main):005> end
=> :run

# Carクラスから、新規インスタンスを生成
irb(main):006> pink_car = Car.new
=> #<Car:0x000000010848a860>

# クラスメソッドを呼び出し
irb(main):007> Car.run
走行します
=> nil
```

## プライベートメソッド
クラス外から呼び出すことのできないメソッドのこと

[![Image from Gyazo](https://i.gyazo.com/ec309377541bfea7ae47853e9e14140d.png)](https://gyazo.com/ec309377541bfea7ae47853e9e14140d)

- メリット
    - Classの外部から呼ばれたら困るメソッドを隔離
        Class外から呼び出すとエラーを起こすメソッドも存在する。プライベートメソッドはClass外から呼び出すことが不可能であるため、誤って呼び出してしまう等によるエラーを事前に防ぐことができる
    - 可読性
        Classの外部から呼び出されるメソッドを探すときに、`private`以下の部分は目を通さなくて良くなる
        繰り返し使用するメソッドも`private`以下に集約できるため、コードをシンプルにできる

### 記述方法
`private`以下のコードは、全てプライベートメソッド

```ruby
class [クラス名]
  def [メソッド名] # インスタンスメソッドの定義
    # インスタンスメソッドの処理
  end
  
  def self.[メソッド名] # クラスメソッドの定義
    # クラスメソッドの処理
  end
  
  private  # private以下の記述はすべてプライベートメソッドになる
  
  def [メソッド名] # プライベートメソッドの定義
    # プライベートメソッドの処理
  end
  
  def [メソッド名] # プライベートメソッドの定義
    # プライベートメソッドの処理
  end
end
```

## インスタンスの生成
クラスメソッドの一種であるnewメソッドを使用することで、インスタンスを生成できる

https://qiita.com/likapantrip/items/655e2c8fc2d4c02eb12e#newメソッド


## インスタンスメソッド
インスタンスが使用できるメソッドであり、属性値を使った処理を行う

### インスタンスメソッドの定義
```ruby
class クラス名
  def インスタンスメソッド名
    # 処理
  end
end
```

### インスタンスメソッドの呼び出し
```ruby
インスタンス名.インスタンスメソッド名(引数)
```

## インスタンス変数
インスタンスが保持する属性を定義するための変数

### イメージ
[![Image from Gyazo](https://i.gyazo.com/e25cd496e1f3ccd65e4a55e9b49cdfa9.png)](https://gyazo.com/e25cd496e1f3ccd65e4a55e9b49cdfa9)

```ruby
class クラス名
  def メソッド名
    @インスタンス変数名 = 値  
  end
end

# Carクラスの定義
irb(main):001* class Car
irb(main):002*   def ride_car(weight)
irb(main):003*     @car_weight = weight # インスタンス変数car_weightに値weightを代入
irb(main):004*   end
irb(main):005> end
=> :ride_car

# Carクラスのインスタンスを生成し、変数pink_carに代入
irb(main):006> pink_car = Car.new
=> #<Car:0x000000010d55c0e0>

# 変数pink_carを出力し、引数900をweightに代入
irb(main):007> pink_car.ride_car(900)
=> 900
```

## 比較整理
### メソッド
|| クラスメソッド | インスタンスメソッド |
|---|---|---|
| 処理 | クラス全体で共通の処理 | クラスから生成されたインスタンスの処理 |
| 使用対象 | クラス | インスタンス |
| コード | def self.クラスメソッド名<br>end | def インスタンスメソッド名<br>end |

### 変数
|| ローカル変数 | クラス変数 | インスタンス変数 |
|---|---|---|---|
| スコープ | 同じメソッド内でのみ、使用可能 | クラス毎に用意される変数であり、各インスタンスで使用可能 | 同じクラスの別インスタンスメソッドで使用可能 |
| 記述方法 | `ローカル変数`<br>※何もつけない | `@@クラス変数`<br>※先頭に@@をつける | `@インスタンス変数`<br>※先頭に@をつける |

#### ローカル変数
別インスタンスメソッドでローカル変数を使うと、エラーになる

```ruby
# Carクラスの定義
irb(main):001* class Car
irb(main):002*   def getname1(name)
irb(main):003*     car_name = name
irb(main):004*     puts car_name
irb(main):005*   end
irb(main):006*   def getname2
irb(main):007*     puts car_name
irb(main):008*   end
irb(main):009> end
=> :getname2

# Carクラスのインスタンスを生成し、変数pink_carに代入
irb(main):010> pink_car = Car.new
=> #<Car:0x0000000109b1dc08>

# 変数pink_carのインスタンスメソッドgetname1を出力する
irb(main):011> pink_car.getname1('ピン子ちゃん')
ピン子ちゃん
=> nil

# 変数pink_carのインスタンスメソッドgetname2を出力できない
irb(main):012> pink_car.getname2
=> `getname2': undefined local variable or method `car_name' for #<Car:0x000000010d691280> (NameError)
```

#### クラス変数
別インスタンスでもクラス変数を使用できる

```ruby
# Carクラスの定義
irb(main):001* class Car
irb(main):002*   @@count = 0
irb(main):003*   def count_car
irb(main):004*     @@count += 1
irb(main):005*     puts "#{@@count}台目のクルマ"
irb(main):006*   end
irb(main):007> end
=> :count_car

# Carクラスのインスタンスを生成し、変数pink_carに代入
irb(main):008> pink_car = Car.new
=> #<Car:0x0000000107dc0980>

# 変数pink_carのインスタンスメソッドcount_carを出力する
irb(main):009> pink_car.count_car
1台目のクルマ
=> nil

# Carクラスのインスタンスを生成し、変数green_carに代入
irb(main):010> green_car = Car.new
=> #<Car:0x0000000107e8cc38>

# 変数green_carのインスタンスメソッドcount_carを出力する
irb(main):011> green_car.count_car
2台目のクルマ
=> nil
```

#### インスタンス変数
別インスタンスメソッドでインスタンス変数を使うと、正常に処理される

```ruby
# Carクラスの定義
irb(main):001* class Car
irb(main):002*   def getname1(name)
irb(main):003*     @car_name = name
irb(main):004*     puts @car_name
irb(main):005*   end
irb(main):006*   def getname2
irb(main):007*     puts @car_name
irb(main):008*   end
irb(main):009> end
=> :getname2

# Carクラスのインスタンスを生成し、変数pink_carに代入
irb(main):010> pink_car = Car.new
=> #<Car:0x000000011037b598>

# 変数pink_carのインスタンスメソッドgetname1を出力する
irb(main):011> pink_car.getname1('ピン子ちゃん')
ピン子ちゃん
=> nil

# 変数pink_carのインスタンスメソッドgetname2を出力できない
irb(main):012> pink_car.getname2
ピン子ちゃん
=> nil
```

# 備考
既存でRubyに定義されているメソッドは、下記を参照

https://qiita.com/likapantrip/items/655e2c8fc2d4c02eb12e