Rubyの変数の定義(定数)

いよいよRubyの変数の定義のラストです。
これまでに[ローカル変数](https://qiita.com/nyan_tech_24/items/bf52e294e86910d23570)と[インスタンス変数](https://qiita.com/nyan_tech_24/items/7bd5bb0bd5e092dbb778)、[クラス変数](https://qiita.com/nyan_tech_24/items/0e673dd9ddb38b2bd0bc)、[グローバル変数](https://qiita.com/nyan_tech_24/items/5894600c6676e69a3d49)について書きました。

今回は定数について書いていきます。

##命名規則
- 先頭が大文字
- 英数字と_で構成される

```ruby
STUDENT = 'Taro'
=> "Taro"
Student_2 = 'Jiro'
=> "Jiro"
Student_3  #何も変数に入れないとエラーが発生する
NameError: uninitialized constant Student_3
```


##スコープ
定数が定義されたクラス・モジュール内、そのクラス・モジュールの内側で定義されたクラス・モジュール内、およびそのクラス・モジュールを継承またはインクルードしているモジュール内クラス名やモジュール名で修飾知れば外部からアクセスが可能

```ruby
Student = "Taro" 
puts Student 
Taro
=> nil

3.times do |n|
  puts Student
end
Taro
Taro
Taro
=> 3 

def students
  Student
end
students           #どこからでも参照可能
=> "Taro"

class Students
  puts Student  
end
Taro                     #どこからでも参照可能
=> nil
```

ただしインスタンスメソッド内では定数を定義することはできない

```ruby
def students
Student = 'Taro'
end
SyntaxError: (irb):2: dynamic constant assignment
```
この理由はメソッドは複数回呼び出すことが前提で、メソッドの中に定数を定義するということは、メソッドを呼び出す際に毎回更新することになるから。
定数は大前提値を変更・更新しないことが目的なのでメソッド内部で定数を定義しようとするとエラーになる。

とはいうものの定数に値を再代入して値を変更することはできる。

```ruby
 Student = 'Taro'
 Student = 'Yamada Taro'
(irb):2: warning: already initialized constant Student
(irb):1: warning: previous definition of Student was here
=> "Yamada Taro"
```
 ただし定数の値の変更には警告が伴う

また定数はmoduleやclassの中では定義ができる。そしてネストを指定して定数の値を変更できる。
ただし、変更ごとに警告はでる。

```ruby
module Teachers
  English = 'Eiko'
end
=> "Eiko"
#ネストを指定して値を変更する
Teachers::English = 'Keiko'
warning: already initialized constant Teachers::English
warning: previous definition of English was here
=> "Keiko"

class MedicalStudents
  Student = 'Hanako'
end
=>"Hanako"
MedicalStudents::Student = 'Yoshiko'
warning: already initialized constant MedicalStudents::Student
warning: previous definition of Student was here
=> "Yoshiko"
```
同じ定数でも構造がクラスやモジュールの異なる階層や場所で定義すればそれぞれ違う値を持つことができる。

```ruby
class Students
  Student = 'Taro'
#Studentsクラス内にMedicalStudentクラスを定義
  class MedicalStudent
    Student = 'Hanako'
  end
#Studentsクラス内にStudentCouncil(生徒会)モジュールを定義
  module StudentCouncil
    Student = 'Jiro'
    #StudentCouncil(生徒会)モジュールにTeamMemberクラスを定義
    class TeamMember
      Student = 'Sabu'
    end
   #StudentCouncil(生徒会)モジュールにSecretary(書記)モジュールを定義
    module Secretary 
      Student = 'Yoshiko'
    end
  end
end

Students::Student
=> "Taro"
Students::MedicalStudent::Student
=> "Hanako"
Students::StudentCouncil::Student
=> "Jiro"
Students::StudentCouncil::TeamMember::Student
=> "Sabu"
Students::StudentCouncil::Secretary::Student
=> "Yoshiko"
```
とうかたちで内部の参照ができる
またクラスを継承したりモジュールをインクルードしても参照できる

```ruby
class University < Students
  puts Students::Student
  puts Students::MedicalStudent::Student
  puts Students::StudentCouncil::Student
  puts Students::StudentCouncil::TeamMember::Student
  puts Students::StudentCouncil::Secretary::Student
end
Taro
Hanako
Jiro
Sabu
Yoshiko
=> nil

#Studentsクラスをモジュールに変更してCramSchool(塾)クラスincludeしてみる
module Students #⬅︎をモジュールに書き変え、Studentsモジュールを定義
Student = 'Taro'
  class MedicalStudent
    Student = 'Hanako'
  end
  module StudentCouncil
    Student = 'Jiro'
    class TeamMember
      Student = 'Sabu'
    end
    module Secretary 
      Student = 'Yoshiko'
    end
  end
end

class CramSchool
  include Students  #Studentsモジュールをインクルードする
  puts Students::Student
  puts Students::MedicalStudent::Student
  puts Students::StudentCouncil::Student
  puts Students::StudentCouncil::TeamMember::Student
    puts Students::StudentCouncil::Secretary::Student
end
Taro
Hanako
Jiro
Sabu
Yoshiko
=> nil
```
というわけで定数でした。

また定数は基本的に変更しないという前提ですが、警告は出るものの変更ができます。
これについて変更できないように定数を定義する方法もありますが、それについてはいずれ書きたいと思います。

##最後に
これまでこれまでに[ローカル変数](https://qiita.com/nyan_tech_24/items/bf52e294e86910d23570)と[インスタンス変数](https://qiita.com/nyan_tech_24/items/7bd5bb0bd5e092dbb778)、[クラス変数](https://qiita.com/nyan_tech_24/items/0e673dd9ddb38b2bd0bc)、[グローバル変数](https://qiita.com/nyan_tech_24/items/5894600c6676e69a3d49)について書き、そして今回は定数について書いてきました。

正直変数について舐めていました。
まだまだ分かってない部分もありそうです。

しかし、変数一つ一つを学んだことで、メソッドやクラス、モジュールなども一緒に勉強ができました。

やはり種の部分から勉強するこで、幹や葉に繋がっていくので、最初の出てくるような部分こそしっかりやることが近道なのかと改めて気づかされました。