super and super( ) {…} in Ruby

lazy.rb를 보다가 알게된 점에 대해서 써보겠습니다.

먼저, super는 자기에게 주어진 모든 인자를 (블럭도 포함) 부모에게 넘깁니다.

class Parent
  def initialize(num)
    @num = num
  end

  def get_parent_num
    @num
  end
end

class Child < Parent
  def initialize(num)
    super
    @num = num
  end

  def get_child_num
    @num
  end
end

>> c = Child.new(3)
=> #<Child:0xb7f4ba90 @num=3>
>> c.get_parent_num
=> 3
>> c.get_child_num
=> 3

잘 모르면 당황할 수 있습니다. super를 메소드 호출이라고만 생각하면 놓치기 쉽겠죠. 다음은 이처럼 super가 부모에게 모든걸 넘겨준다는 점을 사용한 코드입니다.

#!/usr/local/bin/ruby -w

class Parent
def initialize(&blk)
puts “Parent”
@blk = blk
end

def result
@blk.call
end
end

class Child < Parent def initialize(&blk) super puts "Child" cached_result = result super() { puts "Cached: 3+5=#{cached_result}" } end end job = lambda { puts "Computing: 3+5=#{3+5}" return 3+5 } parent = Parent.new(&job) parent.result child = Child.new(&job) child.result [/code] 실행결과는 Parent Computing: 3+5=8 Parent Child Computing: 3+5=8 Parent Cached: 3+5=8 입니다. Child.new 이후부터 보겠습니다. [code lang="ruby"] child = Child.new(&job) [/code] 는 Child.initialize 에 블럭을 넘깁니다. 그러면, [code lang="ruby"] def initialize(&blk) super puts "Child" cached_result = result super() { puts "Cached: 3+5=#{cached_result}" } end [/code] 는 부모에게 그 블럭을 넘기고, "Child"라고 인쇄합니다. 다음, Parent.result 를 호출해 Parent내에서 그 블럭을 계산합니다. 그리고 결과를 받아와 이를 cached_result에 저장합니다. 이제 한번 계산했으니 블럭을 또 계산할 필요는 없겠죠. 그러므로, super( ) {...} 를 통해서 부모에 새로운 블럭을 넘깁니다. 이 새로운 블럭은 캐싱된 결과를 출력하죠. 혹시 lambda가 신경쓰이신다면, 이는 단순히 Proc 에 대한 alias 정도에 지나지 않습니다. 또, [code lang="ruby"] job = lambda { puts "Computing: 3+5=#{3+5}" return 3+5 } [/code] 에서 result 3+ 5 는 순전히 설명을 위해서 넣었습니다. 원래대로라면 계산식만 써놓아야했겠지만 실행 내용을 보이려면 puts를 해야하고 puts는 nil을 반환하는고로 어쩔 수 없었습니다.... 그럼, Child 에서는 블럭을 받아오되 이를 Parent에는 안넘겨주려면 어떻게 해야할까요. [code lang="ruby"] super(&nil) [/code] 이렇게 해야합니다. 왜 이렇게 ugly 하게 코드를 쓰게 만들었을까요. Matz는 다음과 같이 설명합니다.

|”super(&nil)”? IMHO it is ugly and really unnatural. Why not planning a change
|about this for ruby2?

No. “super” is a delegation to the superclass method so that a block
should also be delegated if a block is passed to the method, unless
explicitly specified. Changing it forces “super(&block)” for common
case. IMHO it is ugly and unnatural.

이것이 super와 super( ) { … } 의 비밀(저만 모른건가;;)입니다.

Similar Posts:

Post a Comment

Your email is never published nor shared.