「初めてのRuby」一人勉強会9日目
Ruby をぼちぼち勉強しています。
教材はコレ↓
初めてのRuby
今日は第8章。オブジェクトとクラス
これを読みつつ、つぶやいてみます。
以下、つぶやきメモ。
※1 今のところ、正直あまり Ruby は好きではありません。
※2 オイラがまともにそこそこ書ける言語は C#, Java(5.0より前), Perl です。言語の機能を語っているときはその辺との比較になっているはず
※3 Ruby はまだあんま理解していないので、的外れでトンチンカンな批判してるかも
※4 コードはサンプルそのままのときと、オイラが勝手に変えてるときがあります
インスタンス (p.146 例8-5, 8-6)
とりあえず一番普通っぽいクラスとそのインスタンスの作り方を写経
#!/usr/local/bin/ruby class Duration def initialize(since, till) @since = since @until = till end def self.print(x) puts x end attr_accessor :since, :until end duration = Duration.new(Time.now, Time.now + 3600) p duration.until p duration.since = Time.now Duration.print 1
attr_accessor っていうのを使うと、getter/setter を勝手に作ってくれるらしい。便利だね。
static メソッドは「クラス名.メソッド名」または「self.メソッド名」とするらしい。まあ普通は self をつかうだろうね。
クラスの定義追加 (p.148, 例8-8)
#!/usr/local/bin/ruby class String def caesar; tr 'a-zA-Z', 'n-za-mN-ZA-M' end #カエサル暗号を行うメソッド end puts "Learning Ruby".caesar
組込みクラスも含めて、既存のクラスに定義を追加できるらしい。すげー便利な半面、自重しないと、どこで定義されてるかさっぱり分からないカオスを作れるから注意が必要だねぇ。
さらに同名のメソッドを作ることで上書きまでできるらしいし、上書きの禁止もできるらしい。このへんはエキスパートには必須だろうけど、一般人に対しては、「ご利用は計画的に」だな。
スーパークラスのメソッド呼び出し(p.150, 例8-12)
class Duration def display(target=$>) super target.write "(#{self.since}-#{self.until})" end end duration = Duration.new(Time.now, Time.now + 3600) duration.display
super とだけ書くと、super(target)と同じ意味らしい。引数無しなら super() だって。引数をそのまま渡すことは多いだろうから、便利なのだろうけど、ちょっと直観に反するなぁ。
クラス変数 (p.151 例8-14)
#!/usr/local/bin/ruby class Foo @@class_variable = "foo" def print p @@class_variable end end class Bar < Foo @@class_variable = "bar" def print p @@class_variable end end foo = Foo.new foo.print #=> "bar" bar = Bar.new bar.print #=> "bar"
ぬぉ。クラス変数はサブクラスで書き換えると、スーパークラスに影響が波及するみたい。これは恐いな。クラス変数の利用は自重しないとダメそうだ。
アクセス修飾子 (p.154 例8-16)
#!/usr/local/bin/ruby class Yapoo #デフォルトは public らしい def public_method; end private #以降のメソッドは private def internal_use; end def public_api return internal_use end public :public_api #これで public になる end yapoo = Yapoo.new yapoo.public #ok yapoo.internal_use #エラー
アクセス修飾子の書き方は C++風だね。
特異メソッドで Singleton (p.155 例8-18)
#!/usr/local/bin/ruby CENTRAL_REPOSITORY = Object.new def CENTRAL_REPOSITORY.register(target) @registered_objects ||= [] unless @unregistered_objects.include? target @registered_objects << target end end def CENTRAL_REPOSITORY.unregister(target) @registered_objects ||= [] @registered_objects.delete(target) end
うーん、あんま理解できてないけど、特異メソッドこんなかんじで作っておくと、オブジェクトの単一インスタンスを管理できるってことだよね?
これ一個に管理させてもいいし、Singleton にしたいクラスをこうしてもいい、ってことかな。
特異クラスで Singleton (p.156 例8-19)
#!/usr/local/bin/ruby CENTRAL_REPOSITORY = Object.new class << CENTRAL_REPOSITORY def CENTRAL_REPOSITORY.register(target) @registered_objects ||= [] unless @unregistered_objects.include? target @registered_objects << target end end def CENTRAL_REPOSITORY.unregister(target) @registered_objects ||= [] @registered_objects.delete(target) end end
こうやっても同じだって。トップレベルを汚さないからこっちのほうがいいかな。