いよいよRubyの変数の定義のラストです。
これまでにローカル変数とインスタンス変数、クラス変数、グローバル変数について書きました。
今回は定数について書いていきます。
##命名規則
- 先頭が大文字
- 英数字と_で構成される
STUDENT = 'Taro'
=> "Taro"
Student_2 = 'Jiro'
=> "Jiro"
Student_3 #何も変数に入れないとエラーが発生する
NameError: uninitialized constant Student_3
##スコープ
定数が定義されたクラス・モジュール内、そのクラス・モジュールの内側で定義されたクラス・モジュール内、およびそのクラス・モジュールを継承またはインクルードしているモジュール内クラス名やモジュール名で修飾知れば外部からアクセスが可能
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
ただしインスタンスメソッド内では定数を定義することはできない
def students
Student = 'Taro'
end
SyntaxError: (irb):2: dynamic constant assignment
この理由はメソッドは複数回呼び出すことが前提で、メソッドの中に定数を定義するということは、メソッドを呼び出す際に毎回更新することになるから。
定数は大前提値を変更・更新しないことが目的なのでメソッド内部で定数を定義しようとするとエラーになる。
とはいうものの定数に値を再代入して値を変更することはできる。
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の中では定義ができる。そしてネストを指定して定数の値を変更できる。
ただし、変更ごとに警告はでる。
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"
同じ定数でも構造がクラスやモジュールの異なる階層や場所で定義すればそれぞれ違う値を持つことができる。
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"
とうかたちで内部の参照ができる
またクラスを継承したりモジュールをインクルードしても参照できる
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
というわけで定数でした。
また定数は基本的に変更しないという前提ですが、警告は出るものの変更ができます。
これについて変更できないように定数を定義する方法もありますが、それについてはいずれ書きたいと思います。
##最後に
これまでこれまでにローカル変数とインスタンス変数、クラス変数、グローバル変数について書き、そして今回は定数について書いてきました。
正直変数について舐めていました。
まだまだ分かってない部分もありそうです。
しかし、変数一つ一つを学んだことで、メソッドやクラス、モジュールなども一緒に勉強ができました。
やはり種の部分から勉強するこで、幹や葉に繋がっていくので、最初の出てくるような部分こそしっかりやることが近道なのかと改めて気づかされました。