クラス変数、クラスインスタンス変数、インスタンス変数の違い

# はじめに
クラス変数、クラスインスタンス変数、インスタンス変数の違いについて「なんとなく」理解しているようで、はっきりと説明するのが難しい。この記事では、それぞれの変数の特徴と使い分けについて、身近な例に置き換えて解説したい。

# 説明
Rubyには「クラス変数」「クラスインスタンス変数」「インスタンス変数」の3種類の変数がある。

今回は、これらの違いを「小学校の名前」「小学校の予算」「生徒の情報」に例えて説明していく。


## クラス変数(小学校の名前)
クラス変数の特徴は、以下の通り。

-  クラス全体で値が共有される。
-  クラス内のメソッドやインスタンスメソッドからアクセスできる。
-  サブクラスでも共有される。

例えば、小学校の名前は、すべての生徒に共通して知られている情報である。クラス変数を用いることで、この「小学校の名前」をクラス全体で共有できる。

 ```ruby
 class 小学校
  @@名前 = "さくら小学校" # クラス変数で小学校の名前を設定

  def 名前
    @@名前
　end
end

class 生徒 < 小学校
  def 小学校の名前を確認
    名前
  end
end
    
#生徒が小学校の名前を確認
太郎 = 生徒.new
puts 太郎.小学校の名前を確認 # => さくら小学校

 ```
以上より、「小学校の名前」が全生徒で共有され、名前が変更されると全ての生徒が新しい名前を確認できる。

<img width="300" src="https://japaclip.com/files/elementary-school.png">

## クラスインスタンス変数（小学校の予算）
クラスインスタンス変数の特徴は、以下の通り。
- クラスメソッドでのみアクセスできる。
- クラスごとに独立している。（他のクラスと共有されない。）
- サブクラスには継承されない。

今度は「小学校の予算」で例える。

小学校の予算は、生徒個人が直接確認できるものではなく、小学校クラス内でのみ管理される情報であるとする。クラスインスタンス変数を使うことで、このような「小学校に閉じた情報」を管理が可能。

```ruby
class 小学校
  @予算 = "200万円"  # クラスインスタンス変数で小学校の予算を設定

  def self.予算
    @予算
  end
  
  def 予算          #インスタンスメソッドでアクセスを試みる
    @予算
  end
end

class 生徒 < 小学校
  def 予算を確認
    予算
  end

#生徒が小学校の予算を確認
太郎 = 生徒.new
puts 太郎.予算を確認 # => nil(アクセスできないため、結果はnil)

```

生徒が直接（インスタンスメソッドから）アクセスすることができないため、小学校クラスに用意されたクラスメソッド`小学校.予算`を通して、間接的にアクセスする必要がある。

```ruby
class 生徒 < 小学校
  def 予算を確認
    self.class.予算  # クラスメソッドを通してアクセス
  end
end

太郎 = 生徒.new
puts 太郎.予算を確認 # => "200万円"

```
クラスメソッドを使用すれば、生徒も小学校の予算にアクセスができる。このように、クラスインスタンス変数はクラスに閉じており、インスタンスから直接はアクセスできない。

<img  width = "300"src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjs0I4TZIWgQ7bTjQtcjZvDJFB7kdJBUbdQ-DIw42wWw4fZ6HLoV2kci8u2L6QkhCdK8fvuMjbCLUsfOaTn-Scj59uS5Xy-zXirP69XWXuZEgsGxjGDEr1COLF4-7wPq6kZnr25b8V86K_U/s686/money_kinyu_hikishime.png">
(小学校がお金を守っているイメージです。。)

## インスタンス変数（個々の生徒の情報）
インスタンス変数の特徴は、以下の通り。
- インスタンスメソッドからのみアクセス可能
- 各インスタンスが独立した値を持つ
- 他のインスタンスには影響を与えない

「生徒個々の情報」に例えると、インスタンス変数はそれぞれの生徒が持つ情報。例えば、名前や学年など、個別の生徒が持つ情報として管理。インスタンスごとに異なる情報を持ち、他のインスタンスに影響を与えません。

```ruby
class 生徒
  def initialize(名前, 学年)
    @名前 = 名前  # この生徒だけが持っている情報
    @学年 = 学年  # この生徒だけが持っている情報
  end

  def 名前
    @名前
  end

  def 学年
    @学年
  end
end

太郎 = 生徒.new("太郎", 1)
花子 = 生徒.new("花子", 2)

puts 太郎.名前 # => "太郎"
puts 太郎.学年 # => 1
puts 花子.名前 # => "花子"
puts 花子.学年 # => 2

```
以上より、太郎と花子というそれぞれの生徒が異なる名前と学年を持っており、互いに干渉しない独立した情報として管理。

<img width="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieB-cSJ8p4QHnxTcubdsiz5kRTgUdyJWnZf-Raki0tLJUADQU4puuv0p5DQ_N1BGAdEcEMRbm7ZpzCL5fNyLa9Jp8BtAxxw107waMhS3nrEosso7RR-I_zrlbngIEYoHTQ4QwyNZOB5FQh/s800/tsugaku.png">


# 最後に
各変数の違いを下記の通りとりまとめた。これからは、目的に応じて各変数を扱いたい。特に、クラス変数はクラス全体で共有されているので、用途によっては問題が発生してしまう。


| 種類                 | 共有範囲            | アクセス方法                     | 継承への影響      | 例                    |
|----------------------|---------------------|----------------------------------|-------------------|-----------------------|
| クラス変数           | クラス全体で共有    | クラス・インスタンスメソッドから  | サブクラスでも共有 | 小学校の名前          |
| クラスインスタンス変数 | クラス単位で独立    | クラスメソッドのみ                | 継承されない       | 小学校の予算          |
| インスタンス変数     | 各インスタンスで独立 | インスタンスメソッドから          | 他のインスタンスに影響なし | 生徒の情報（名前や学年） |