LoginSignup
23
23

More than 5 years have passed since last update.

クロージャって何? どこがオブジェクト指向と似てるの? をRubyで説明するために書いたコード

Last updated at Posted at 2013-02-24

タイトルの通り。

人にコードだけ見せて書き捨てるのももったいない気がしたので、説明を加筆して公開。

  • わからないところがあったら質問ください
  • 誤りや語弊のある表現があれば突っ込みください

オブジェクト指向とは何か、と語りはじめるとたいへん長い話になり、僕は議論できるほど理解を深めてないので 「諸説あるが」 で済ませるとして、ここではRubyのクラスベースオブジェクト指向プログラミング、つまりC++風の抽象データ型に基くOOPの話になります。 乱暴だなあ

class A
  def initialize (arg)
    # インスタンス変数(メンバ変数)定義
    # これは同じインスタンスのメソッドの中からしか参照できない
    @x = arg.upcase
  end

# メソッド定義
  def call
    # インスタンス変数@xの値を取り出す
    return @x
  end
end

# 定数に函数を代入してる
B = ->(arg){
  # 函数定義の中で変数定義
  x = arg.upcase
  # Bが呼びだされると、このfuncが新たに生成される
  func = ->{
    # この函数の中からは変数xを参照できる
    # むしろxは、Bの函数定義内からしか参照できない=閉ぢてる=クロージャ
    return x
  }
  return func
}

# インスタンス生成
a1 = A.new("foo")
# メソッド呼び出し
p a1.call

# インスタンス生成みたいなもの
b1 = B.("foo")
p b1.call

### aとa2, bとb2が新しい別のインスタンスであることを確認

# インスタンス生成
a2 = A.new("bar")
# メソッド呼び出し
p a2.call

# インスタンス生成みたいなもの
b2 = B.("baz")
p b2.call
  • a1a2@x と、 b1b2 から見た x は、それぞれ別物。
  • B 内部の x は、この場合 func からしか参照することができない
    • B と名前を付けられた函数定義が、変数のスコープを作ってる
    • 函数定義によって閉ぢたスコープができるから クロージャ(閉包) って呼ばれる
    • x の中身は外部から参照したり破壊されたりしないので 隠しておける
    • これってつまり一般にオブジェクト指向の特徴の一つだと呼ばれることがある 「隠蔽」だよね
  • A@x はインスタンスのメソッドからしか参照・操作できない (建前、裏技あり)
    • でも A のなかに def x; @x; end とか def x= (arg); @x = arg; end みたいなメソッドを定義すれば a.x = "foo" みたいに C# のプロパティと似たようなことができる
    • でもって、 attr_accessor :x と書けば、上記の定義とまったく同じものを省略することができる。ぐぐれ。
    • Ruby の世界では x= は一つのメソッド名。なのに a.x = "foo" とか書けちゃう。ふしぎふしぎ。
  • 僕は JavaScript とか Scheme とか素人だけど、たいへんお世話になってます
  • Python はクロージャを作りにくかった(上のコードを素直に移植してもうまくいかない)んだけど、Python 3 では nonlocal が追加されたので作りやすくなりました
  • Ruby でもクロージャは使へるけど、ふつうは素直にクラスを使って表現するべき
  • でも最近仕事で PHP は 変数のスコープがファイルローカルじゃない ときいて、クロージャを作って call_user_func で呼び出す必要があった (しろめ)

補足

  • Ruby の ->(){ ... } は函数オブジェクトを作成する構文
    • lambda{ ... } って書いてもほとんど同じなので、文脈によって読みやすさ、かっこよさで選んで良い
  • ( あとでまた書く )

合せて読まれたい

そして突っ込みが欲しい

23
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
23