1. クラス名は大文字で始まるのだ
まずこれにびっくり。
#!/usr/bin/env ruby
class myclass # ← 小文字
def initialize()
end
def sub()
puts 'sub なのだ'
end
end
c = myclass.new()
c.sub()
てなソースを書いて実行したら
/home/hogehoge/lang/ruby/class/class01.rb: --> /home/hogehoge/lang/ruby/class/class01.rb
expected a constant name after `class`
> 3 class myclass # ← 小文字
> 10 end
/home/hogehoge/lang/ruby/class/class01.rb:3: class/module name must be CONSTANT (SyntaxError)
class myclass # ← 小文字
^~~~~~~
怒られちゃいました。
なかなか制約があるのですなぁ。クラス名の先頭の文字は大文字でないと文法エラーになるんですって。
そういや Eclipse 上で赤いマークが出てたな。
書き直したら
#!/usr/bin/env ruby
class Myclass # ← 大文字
def initialize()
end
def sub()
puts 'sub なのだ'
end
end
c = Myclass.new()
c.sub()
正常に動作しました。
sub なのだ
2. コンストラクタ
コンストラクタには initialize というメソッドを定義します。
#!/usr/bin/env ruby
class Myclass
def initialize()
puts 'コンストラクタなのだ'
end
def sub()
puts 'sub なのだ'
end
end
c = Myclass.new()
c.sub()
上記のソースを実行すると、下記の結果が得られます。
コンストラクタなのだ
sub なのだ
3. デストラクタはないのだ
ruby には、他の言語でいうところのデストラクタはないそうで・・・。
検索すると「DestructorはないけどFinalizerはあった件 - komamitsu.log」に記事がありましたので、それを参考にさせていただきます。
ObjectSpace.define_finalizer というメソッドを使うとファイナライザーの定義ができるそうな・・・。
上記参考サイトのままでない方法でやってみるとうまくいかなかったので、更に「module function ObjectSpace.#define_finalizer (Ruby 2.5.0)」を参考にして
class Myclass
def Myclass.callback
proc {
puts 'ファイナライザなのだ'
}
end
def initialize()
puts 'コンストラクタなのだ'
ObjectSpace.define_finalizer(self, Myclass.callback)
end
def sub()
puts 'sub なのだ'
end
end
1.upto 2 do | i |
c = Myclass.new()
c.sub()
end
これを実行すると
コンストラクタなのだ
sub なのだ
コンストラクタなのだ
sub なのだ
ファイナライザなのだ
ファイナライザなのだ
となります。
デストラクタでなくファイナライザなので完全に消滅するときにしか動作しないようです。
処理を proc で囲んでいないとエラーになっちゃいます。
class Myclass
def Myclass.callback
puts 'ファイナライザなのだ' # proc で囲んでいない
end
def initialize()
puts 'コンストラクタなのだ'
ObjectSpace.define_finalizer(self, Myclass.callback)
end
def sub()
puts 'sub なのだ'
end
end
1.upto 2 do | i |
c = Myclass.new()
c.sub()
end
実行結果はこうなります。
/home/hogehoge/lang/ruby/class/class05.rb:9:in `define_finalizer': wrong type argument NilClass (should be callable) (ArgumentError)
ObjectSpace.define_finalizer(self, Myclass.callback)
^^^^^^^^^^^^^^^^^^^^^^
from /home/hogehoge/lang/ruby/class/class05.rb:9:in `initialize'
from /home/hogehoge/lang/ruby/class/class05.rb:18:in `new'
from /home/hogehoge/lang/ruby/class/class05.rb:18:in `block in <main>'
from /home/hogehoge/lang/ruby/class/class05.rb:17:in `upto'
from /home/hogehoge/lang/ruby/class/class05.rb:17:in `<main>'
コンストラクタなのだ
ファイナライザなのだ
2、4行目は「DestructorはないけどFinalizerはあった件 - komamitsu.log」や「Rubyコーディング規約」にはメソッドの前には、クラス名でなく self と書くように記述してあるんですけど。
class Myclass
def self.callback
proc {
puts 'ファイナライザなのだ'
}
end
def initialize()
puts 'コンストラクタなのだ'
ObjectSpace.define_finalizer(self, self.callback)
end
def sub()
puts 'sub なのだ'
end
end
1.upto 2 do | i |
c = Myclass.new()
c.sub()
end
て書くと結果はこうなっちゃいました。
/home/hogehoge/lang/ruby/class/class06.rb:11:in `initialize': undefined method `callback' for an instance of Myclass (NoMethodError)
ObjectSpace.define_finalizer(self, self.callback)
^^^^^^^^^
from /home/hogehoge/lang/ruby/class/class06.rb:20:in `new'
from /home/hogehoge/lang/ruby/class/class06.rb:20:in `block in <main>'
from /home/hogehoge/lang/ruby/class/class06.rb:19:in `upto'
from /home/hogehoge/lang/ruby/class/class06.rb:19:in `<main>'
コンストラクタなのだ
4. クラス名・メソッド名・void
クラス名・メソッド名を取得するにはそれ用のメソッドを定義するらしい。
これに関しては「メソッドの中からクラス名とメソッド名を取得する - Qiita」を参考にさせていただきました。
引数のないメソッド、C言語では void で定義するのですが、ruby では () 自体を省略するようで、これは理にかなっている。
class Myclass
def initialize()
end
def self.class_name
self.name
end
def self.class_method_name
__method__
end
def sub1(param)
puts("[#{self.class.name}.#{__method__}]なのだ引数は[#{param}]")
end
def sub2
puts("[#{self.class.name}.#{__method__}]なのだ引数はない")
end
end
c = Myclass.new()
c.sub1('ppp')
c.sub2
というソースを書いて実行すると下記の結果が得られます。
[Myclass.sub1]なのだ引数は[ppp]
[Myclass.sub2]なのだ引数はない
5. 継承
class 派生先 < 継承元
と書くことでクラスの継承ができるようです。
「クラスを継承する - クラスの継承 - Ruby入門」を参考にさせていただきました。
class BaseClass
def initialize
end
def self.class_name
self.name
end
def self.class_method_name
__method__
end
end
class MyClass < BaseClass
def initialize
end
def sub1(param)
puts("[#{self.class.name}.#{__method__}]なのだ引数は[#{param}]")
end
def sub2
puts("[#{self.class.name}.#{__method__}]なのだ引数はない")
end
end
c = MyClass.new
c.sub1('popopo')
c.sub2
というソースを書いて実行すると下記の結果が得られます。
[MyClass.sub1]なのだ引数は[popopo]
[MyClass.sub2]なのだ引数はない