Ruby Language
메시지 전달 중
수색…
소개
객체 지향 디자인 에서 객체 는 메시지를 받고 그에 응답 합니다. Ruby에서 메시지를 보내는 것은 메서드를 호출하고 해당 메서드의 결과가 응답입니다.
Ruby에서 메시지 전달은 동적입니다. 메시지가 도착할 때 회신하는 방법을 정확하게 알기보다는 루비는 사전 정의 된 규칙 집합을 사용하여 회신 할 수있는 방법을 찾습니다. 이러한 규칙을 사용하여 메시지에 끼어 들거나 회신하거나 다른 개체로 보내거나 다른 작업 중에서 수정할 수 있습니다.
객체가 메시지를받을 때마다 Ruby는 다음을 검사합니다.
- 이 객체가 싱글 톤 클래스를 가지며이 메시지에 응답 할 수 있습니다.
- 이 객체의 클래스를 찾은 다음 클래스의 조상 체인을 찾습니다.
- 하나씩이 조상에 메서드를 사용할 수 있는지 확인하고 체인을 위로 이동합니다.
상속 체인을 통해 전달되는 메시지
class Example
def example_method
:example
end
def subexample_method
:example
end
def not_missed_method
:example
end
def method_missing name
return :example if name == :missing_example_method
return :example if name == :missing_subexample_method
return :subexample if name == :not_missed_method
super
end
end
class SubExample < Example
def subexample_method
:subexample
end
def method_missing name
return :subexample if name == :missing_subexample_method
return :subexample if name == :not_missed_method
super
end
end
s = Subexample.new
SubExample#subexample_method
적합한 메소드를 찾으려면 먼저 Ruby는 SubExample
조상 체인을 SubExample
SubExample.ancestors # => [SubExample, Example, Object, Kernel, BasicObject]
SubExample
부터 시작합니다. subexample_method
메시지를 보내면 Ruby는 사용 가능한 하나의 SubExample을 선택하고 Example#subexample_method
무시합니다.
s.subexample_method # => :subexample
SubExample
후에는 Example
을 확인합니다. example_method
를 보내면 Ruby는 SubExample
이 회신 할 수 있는지 여부를 확인합니다. 루비는 사슬을 따라 올라갈 수 없으므로 Example
합니다.
s.example_method # => :example
루비가 정의 된 모든 메소드를 검사 한 후 method_missing
을 실행하여 응답 여부를 확인합니다. missing_subexample_method
를 보내면 Ruby는 SubExample
정의 된 메소드를 찾을 수 없으므로 Example
이동합니다. Example
또는 체인 중 상위에있는 다른 클래스에서 정의 된 메소드를 찾을 수 없습니다. 루비는 다시 시작하여 method_missing
실행합니다. SubExample
method_missing
은 missing_subexample_method
응답 할 수 있습니다.
s.missing_subexample_method # => :subexample
그러나 메소드가 정의되면 루비는 정의 된 버전을 사슬에서 더 높더라도 사용합니다. 예를 들어, not_missed_method
method_missing
이 SubExample
응답 할 수 있다고하더라도 not_missed_method
를 보내면, Ruby는 그 이름을 가진 정의 된 메소드가 없기 때문에 SubExample
을 따라 SubExample
Example
를 찾습니다.
s.not_missed_method # => :example
모듈 구성을 통과하는 메시지
루비는 객체의 조상 체인 위로 이동합니다. 이 체인에는 모듈과 클래스가 모두 포함될 수 있습니다. 체인을 위로 이동하는 것과 같은 규칙이 모듈에도 적용됩니다.
class Example
end
module Prepended
def initialize *args
return super :default if args.empty?
super
end
end
module FirstIncluded
def foo
:first
end
end
module SecondIncluded
def foo
:second
end
end
class SubExample < Example
prepend Prepended
include FirstIncluded
include SecondIncluded
def initialize data = :subexample
puts data
end
end
SubExample.ancestors # => [Prepended, SubExample, SecondIncluded, FirstIncluded, Example, Object, Kernel, BasicObject]
s = SubExample.new # => :default
s.foo # => :second
메시지 인터럽트
메시지를 중단하는 데는 두 가지 방법이 있습니다.
- 정의되지 않은 메시지를 중단하려면
method_missing
을 사용하십시오. - 체인 중간에서 메시지를 가로 채기위한 메소드를 정의하십시오.
메시지를 중단 한 후에는 다음을 수행 할 수 있습니다.
- 그들에게 대답하십시오.
- 다른 곳으로 보냅니다.
- 메시지 또는 그 결과를 수정하십시오.
method_missing
통한 인터럽트 및 메시지에 대한 답장 :
class Example
def foo
@foo
end
def method_missing name, data
return super unless name.to_s =~ /=$/
name = name.to_s.sub(/=$/, "")
instance_variable_set "@#{name}", data
end
end
e = Example.new
e.foo = :foo
e.foo # => :foo
메시지 가로 채기 및 수정 :
class Example
def initialize title, body
end
end
class SubExample < Example
end
이제 우리의 데이터가 "title : body"라고 상상해 봅시다. Example
을 호출하기 전에 데이터를 분할해야합니다. SubExample
initialize
를 정의 할 수 있습니다.
class SubExample < Example
def initialize raw_data
processed_data = raw_data.split ":"
super processed_data[0], processed_data[1]
end
end
메시지 가로 채기 및 다른 개체로 보내기 :
class ObscureLogicProcessor
def process data
:ok
end
end
class NormalLogicProcessor
def process data
:not_ok
end
end
class WrapperProcessor < NormalLogicProcessor
def process data
return ObscureLogicProcessor.new.process data if data.obscure?
super
end
end