Rubyのインスタンス変数・メソッドとクラス変数・メソッドを検証する
Rubyを勉強していて、インスタンス変数・メソッドとクラス変数・メソッドの扱いについて理解するのに時間を要したので、そのときの検証内容を備忘録として記載。
ここではRubyのバージョンは2.4.1
を利用。
クラスで検証
まずは基本仕様。
- インスタンス変数はインスタンスメソッドしかアクセスできない
- クラス変数はインスタンスメソッドとクラスメソッドの両方アクセスできる
- クラスインスタンス変数はそのクラス内で定義されたクラスメソッドしかアクセスできない
Rubyの検証用サンプルコード
class Test
@c_i_var = 0
@@c_var = 10
var = 'var'
def initialize
@i_var = 100
end
def test
@i_var += 1
@@c_var += 1
self
end
def examine1
p 'Test::examine1'
p @i_var, @c_i_var, @@c_var
self
end
def Test.examine2
@c_i_var += 1
p 'Test::examine2'
p @i_var, @c_i_var, @@c_var
Test.new
end
def examine3
Test
end
p 'Test::var'
p var
end
class Test2 < Test
def Test2.examine2
p 'Test2::examine2'
p @i_var, @c_i_var, @@c_var
end
end
t = Test.new
t.test.examine1
Test.examine2.test.examine1.examine3.examine2
Test2.examine2
サンプルコードの出力結果
"Test::var"
"var"
"Test::examine1"
101
nil
11
"Test::examine2"
nil
1
11
"Test::examine1"
101
nil
12
"Test::examine2"
nil
2
12
"Test2::examine2"
nil
nil
12
判明したこと
- クラス
Test1
のインスタンスメソッドexamin1
とクラスメソッドexamin2
の実行結果から「インスタンス変数はインスタンスメソッドしかアクセスできない」と「クラス変数はインスタンスメソッドとクラスメソッドの両方アクセスできる」が判明。 - クラス
Test1
とクラスTest2
のクラスメソッドexamine2
の実行結果から、「クラスインスタンス変数はそのクラス内で定義されたクラスメソッドしかアクセスできない」が判明 - クラス内でローカル変数を定義してもエラーにならない。またクラス内で定義されたローカル変数はインスタンスメソッドとクラスメソッドの両方からアクセスできない。
p var
が実行されるのは最初のインスタンス生成時の1度だけ。 - クラス変数とクラスインスタンス変数の値はインスタンス間で共有される
- インスタンス変数はインスタンス間で共有されない
その他
クラス変数を定義すると"bad code style"という警告がでるので、実際の運用では使わないようにする。
浅いコピーと深いコピーをしたときのクラス変数とインスタンス変数
こちらでPython3で浅いコピーと深いコピーをしたときのクラス変数とインスタンス変数の変化について検証したが、Rubyでの挙動も確認した。
結果は、Python3と同様に深いコピーでもクラス変数の値が変更されている。
Rubyの検証用サンプルコード
class Test
@@c_var = 2
def initialize(val)
@i_var = val
end
def inspect
'%d, %d' % [@@c_var, @i_var]
end
def examine1
@i_var += 2
self
end
def examine2
@@c_var += 2
self
end
end
t1 = Test.new(3)
t1.examine1.examine2
p t1
p Test.new(3)
puts '--- shallow copy ---'
t2 = t1.clone
t2.examine1.examine2
p t1
p t2
p Test.new(3)
puts '--- deep copy ---'
t3 = Marshal.load(Marshal.dump(t1))
t3.examine1.examine2
p t1
p t2
p t3
p Test.new(3)
サンプルコードの出力結果
4, 5
4, 3
--- shallow copy ---
6, 5
6, 7
6, 3
--- deep copy ---
8, 5
8, 7
8, 7
8, 3