tsucchi’s diary(元はてなダイアリー)

はてなダイアリー(d.hatena.ne.jp/tsucchi1022)から移行したものです

「初めての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 をつかうだろうね。

@がインスタンス変数。コンストラクタが initialize。このへんはちょっと変わっているかも。

クラスの定義追加 (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

こうやっても同じだって。トップレベルを汚さないからこっちのほうがいいかな。

オーバーロード (p.163-164)

メソッドの引数に型情報を渡せないから、オーバーロードはできないらしい。メソッド内で振り分けるしかないみたい。不便だけどこれは Perl も同じ。型の無い言語の宿命だねぇ。。。

なんかあんまり理解できてないけど、とりあえずおしまい。クラスは Ruby の主要機能だから、これからじっくり学んでいきたいです。

9章に続く(多分)