Ruby에서 슈퍼클래스 인수 통과 제어

Ruby 클래스 기반 프로그래밍에서 서브클래스 메서드의 슈퍼클래스 버전은 항상 super 키워드를 사용하여 명시적으로 호출됩니다. 하지만 super를 사용하는 데 약간의 뉘앙스가 있습니다. 특히 인수와 블록을 기본 클래스에 전달할 때(또는 전달하지 않을 때) 그렇습니다. RubyTapas 아카이브의 이 샘플에서 이러한 "고장"에 대해 이야기하겠습니다.

Director's commentary: 이것은 원래 2012년 10월에 RubyTapas #14로 출판되었습니다. 저는 대본에서 "아시다시피"라고 말하는 습관이 있었습니다. 에피소드를 시작하고 "오 이건 새로운 게 아니야"라고 생각하세요. 지금은 그런 말을 많이 하지 않지만, 여전히 가끔 "알다시피"라고 합니다. 나는 내 배경 자료를 언급하고 시청자가 그것에 대해 자신을 위치시킬 것이라고 믿는 것이 훨씬 더 편해졌습니다.

여기서 더 "진짜"예제를 제시하지 않은 제 자신에게 약간 화가 났습니다. 따라하기가 더 어렵다고 생각합니다. 1주일에 3화(!) 시대로 돌아가서 급하게 쓰는 건 좀 자제하겠습니다.

비디오 스크립트 및 코드를 보려면 아래로 스크롤하십시오.



슈퍼클래스 메서드 호출에 대해 이야기해 봅시다.

아시다시피 클래스 Child 가 클래스 Parent 에서 상속되고 둘 다 메서드 #hello 를 정의할 때 ChildParent 를 사용하여 #hellosuper 구현을 참조할 수 있습니다.

class Parent
  def hello(subject="World")
    puts "Hello, #{subject}"
  end
end


class Child < Parent
  def hello(subject)
    super(subject)
    puts "How are you today?"
  end
end


Child.new.hello("Bob") 


Hello, Bob How are you today?


자식 구현에 전달된 것과 동일한 인수를 사용하여 부모 구현을 호출하려는 경우 super 에 대한 인수를 생략할 수 있습니다. 이것은 괄호를 생략한 경우에만 작동합니다.

class Child < Parent
  def hello(subject)
    puts super
    puts "How are you today?"
  end
end



이렇게 하면 상위 메서드의 매개 변수 목록을 변경해도 이를 호출하는 모든 호출super을 찾아 업데이트해야 하는 것을 의미하지 않기 때문에 코드가 덜 취약해집니다.

때때로 우리는 0개의 인수가 슈퍼클래스 메서드에 전달되도록 강제하고 싶을 수 있습니다. 이 경우 빈 괄호를 그대로 두지 않고 명시적으로 제공하는 것을 기억하는 것이 중요합니다.

다음은 기본 제목을 사용해야 함을 나타내는 특수 플래그를 사용하는 버전Child입니다. 플래그가 전달되면 빈 괄호를 사용하여 super를 호출하여 수퍼클래스 메서드가 subject의 기본값을 사용하도록 합니다.

class Child < Parent
  def hello(subject=:default)
    if subject == :default
      super() 
      puts "How are you today?"
    else
      super(subject)
      puts "How are you today?"
    end
  end
end


Child.new.hello(:default)


Hello, World How are you today?


그러나 여기에는 함정이 있습니다. 명시적으로 빈 괄호가 있더라도 super를 호출하면 여전히 자식 메서드에 지정된 모든 블록을 자동으로 전달합니다.

무슨 뜻인지 보여주기 위해 부모 클래스 메서드를 수정하여 블록을 가져온 다음 #hello 호출에 블록을 전달해 보겠습니다.

class Parent
  def hello(subject="World")
    puts "Hello, #{subject}"
    if block_given?
      yield
      puts "Well, nice seeing you!"
    end
  end
end


Child.new.hello(:default) do
  puts "Hi there, Child!"
end
# >> Hello, World
# >> Hi there, Child!
# >> Well, nice seeing you!
# >> How are you today?


Hello, World Hi there, Child! Well, nice seeing you! How are you today?


보시다시피 super 에 대한 빈 인수 목록에도 불구하고 블록이 예기치 않게 전달되어 출력이 약간 뒤섞입니다.

전달되는 블록을 억제하려면 특수 인수&nil를 사용해야 합니다.

class Child < Parent
  def hello(subject=:default)
    if subject == :default
      super(&nil) 
      puts "How are you today?"
    else
      super(subject, &nil)
      puts "How are you today?"
    end
  end
end


Child.new.hello(:default) do
  puts "Hi there, Child"
end


Hello, World How are you today?


이 뻔하지 않은 기술은 블록이 암시적으로 수퍼클래스 메서드로 전달될 가능성을 제거합니다.
super 키워드와 관련된 몇 가지 다른 트릭이 있지만 future episode에 대해 저장하겠습니다. Happy hacking!

좋은 웹페이지 즐겨찾기