Rubyの勉強 (5) - クラス
クラスの定義
クラスの定義はclass〜end
class Hello def hello(str) puts "Hello, #{str}" end end if __FILE__ == $0 Hello.new.hello("Ruby") # Hello, Ruby end
newでオブジェクトを生成する.メソッドの呼び出しは.を用いる.__FILE__はそれが書かれているファイル名,$0は実行中のスクリプト名なので,このスクリプトをそのまま実行したときはif文が実行される.
オブジェクト生成時にはnewの引数がinitializeに渡され実行される.
class Hello def initialize(str) @str = str end def hello() puts "Hello, #{@str}" end end if __FILE__ == $0 Hello.new("Ruby").hello() # Hello, Ruby end
継承
継承は'<'を用いて行う.perldoc perlbootを参考にした.動物をクラス化している.
class Animal def speak puts "a #{self.class} goes #{self.sound}!" end def sound "unknown" end end class Cow < Animal def sound "moooo" end end class Horse < Animal def sound "neigh" end end class Sheep < Animal def sound "baaaah" end end if __FILE__ == $0 for a in [Cow, Horse, Sheep] a.new.speak end end
$ ruby animal.rb a Cow goes moooo! a Horse goes neigh! a Sheep goes baaaah!
アクセサ
そのままインスタンス変数を返すだけならばattr_readerメソッドを実行することでそのインスタンス変数の値を返すアクセサを生成することができる.
class Animal attr_reader :sound def initialize(sound) @sound = sound end def speak puts "a #{self.class} goes #{self.sound}!" end end class Cow < Animal def initialize @sound = "mooo" end end class Horse < Animal def initialize @sound = "neigh" end end class Sheep < Animal def initialize @sound = "baaaah" end end if __FILE__ == $0 for c in [Cow, Horse, Sheep] a = c.new puts "#{a.class} ==> #{a.sound}" end end
インスタンス変数への代入
演算子=をオーバーライドすることでインスタンス変数への代入を行える.
class Animal def initialize(sound) @sound = sound end def sound @sound end def sound=(sound) @sound = sound end end if __FILE__ == $0 a = Animal.new("boo") puts a.sound # boo a.sound = "oink" puts a.sound # oink end
attr_writerを用いることで自動生成できる
class Animal attr_reader :sound attr_writer :sound def initialize(sound) @sound = sound end end
というか,attr_accessorで読み取り書き込みの両方ができる
class Animal attr_accessor :sound def initialize(sound) @sound = sound end end
クラス変数とクラスメソッド
カウンタを作ってみる.カウンタごとに何回数えたかを表すインスタンス変数@countと全てのカウンタで何回カウントしたかを表すクラス変数@@total_countを用いている.クラスメソッドは「クラス名.メソッド名」で定義する.
class Counter attr_reader :count @@total_count = 0 def initialize(n=0) @count = n end def inc @count += 1 @@total_count += 1 end def Counter.total_count @@total_count end end if __FILE__ == $0 c1 = Counter.new c2 = Counter.new(2) puts "c1: #{c1.count}" # 0 puts "c2: #{c2.count}" # 2 puts "Total: #{Counter.total_count}" c1.inc c2.inc puts "c1: #{c1.count}" # 1 puts "c2: #{c2.count}" # 3 puts "Total: #{Counter.total_count}" # 2 end
アクセス制御
アクセス制御はC++と同じようにpublic,protected,privateがあるデフォルトではpublic.privateにしたい場合は以下のようにする.
class Sample def foo puts "this is private" end def bar puts "this is public" end private :foo end if __FILE__ == $0 s = Sample.new s.bar s.foo end
$ ruby private.rb this is public private.rb:14: private method `foo' called for #<Sample:0x1d3300> (NoMethodError)