Method
Method
Method 객체는 Object#method이 만들어내며, 특정 객체(클래스만이 아니라)에 묶여 있는 메서드예요. 객체 안에서 그 메서드를 호출하는 데 쓸 수 있고, 반복자(iterator)에 블록으로 넘길 수도 있어요. 또 한 객체에서 풀어내(UnboundMethod 만들기) 다른 객체에 다시 묶을 수도 있어요.
class Thing
def square(n)
n*n
end
end
thing = Thing.new
meth = thing.method(:square)
meth.call(9) #=> 81
[1, 2, 3].collect(&meth) #=> [1, 4, 9]
[1, 2, 3].each(&method(:puts)) #=> prints 1, 2, 3
출처: Ruby 4.0 API
본문
Method 객체는 &method(:이름)처럼 &를 붙여 블록 자리에 그대로 넘길 수 있어요. 이렇게 하면 "이 객체의 이 메서드를 블록으로 써라"라는 뜻이 돼요.
Public Instance Methods
self << g → a_proc
주어진 g와 이 메서드를 합성한 proc을 돌려줘요. 돌려받은 proc은 가변 인자를 받아요. 먼저 g를 인자로 호출한 뒤, 그 반환값을 self에 넘겨 호출해요.
def f(ary) = ary << 'in f'
f = self.method(:f)
g = proc { |ary| ary << 'in proc' }
(f << g).call([]) # => ["in proc", "in f"]
meth == other_meth → true or false
두 메서드 객체는 같은 객체에 묶여 있고 같은 메서드 정의를 가리키며, 그 메서드를 정의한 클래스가 같은 클래스/모듈일 때 같다고 판정돼요. eql?로도 부를 수 있어요.
method === obj → result_of_method
지정된 인자로 이 메서드를 호출해, 그 반환값을 돌려줘요. === 방식 덕분에 case 문의 when 절 대상으로 메서드 객체를 쓸 수 있어요.
m = 12.method("+")
m.call(3) #=> 15
m.call(20) #=> 32
require 'prime'
case 1373
when Prime.method(:prime?)
# ...
end
call의 별칭이에요.
self >> g → a_proc
이 메서드와 주어진 g를 합성한 proc을 돌려줘요. <<와 반대 방향이에요. 먼저 self를 인자로 호출한 뒤, 그 반환값을 g에 넘겨 호출해요.
def f(ary) = ary << 'in f'
f = self.method(:f)
g = proc { |ary| ary << 'in proc' }
(f >> g).call([]) # => ["in f", "in proc"]
meth[args, ...] → obj
지정된 인자로 이 메서드를 호출해 반환값을 돌려줘요. call의 별칭이에요.
arity → integer
메서드가 받는 인자 수를 나타내는 값을 돌려줘요. 고정 개수의 인자를 받는 메서드는 음이 아닌 정수를 돌려주고, 가변 인자를 받는 Ruby 메서드는 -n-1을 돌려줘요(여기서 n은 필수 인자 수). 키워드 인자는 하나의 추가 인자로 취급되며, 어떤 키워드 인자가 필수면 그 추가 인자도 필수로 간주돼요. C로 작성된 메서드가 가변 인자를 받으면 -1을 돌려줘요.
class C
def one; end
def two(a); end
def three(*a); end
def four(a, b); end
def five(a, b, *c); end
def six(a, b, *c, &d); end
def seven(a, b, x:0); end
def eight(x:, y:); end
def nine(x:, y:, **z); end
def ten(*a, x:, y:); end
end
c = C.new
c.method(:one).arity #=> 0
c.method(:two).arity #=> 1
c.method(:three).arity #=> -1
c.method(:four).arity #=> 2
c.method(:five).arity #=> -3
c.method(:six).arity #=> -3
c.method(:seven).arity #=> -3
c.method(:eight).arity #=> 1
c.method(:nine).arity #=> 1
c.method(:ten).arity #=> -2
"cat".method(:size).arity #=> 0
"cat".method(:replace).arity #=> 1
"cat".method(:squeeze).arity #=> -1
"cat".method(:count).arity #=> -1
box → box or nil
meth가 정의된 Ruby::Box를 돌려줘요.
call(args, ...) → obj
지정된 인자로 이 메서드를 호출해 반환값을 돌려줘요. ===, []로도 부를 수 있어요.
m = 12.method("+")
m.call(3) #=> 15
m.call(20) #=> 32
clone → new_method
이 메서드의 복제본을 돌려줘요.
class A
def foo
return "bar"
end
end
m = A.new.method(:foo)
m.call # => "bar"
n = m.clone.call # => "bar"
curry → proc
curry(arity) → proc
메서드에 기반한 커리된(curried) proc을 돌려줘요. proc을 메서드의 arity보다 적은 수의 인자로 호출하면 또 다른 커리된 proc이 돌아와요. 메서드 시그니처를 충족할 만큼 충분한 인자가 모였을 때만 실제로 메서드가 호출돼요. 가변 인자를 가진 메서드를 커리할 때는, 메서드가 호출되기 전에 몇 개의 인자가 필요한지를 정하기 위해 선택적 arity 인자를 주면 돼요.
def foo(a,b,c)
[a, b, c]
end
proc = self.method(:foo).curry
proc2 = proc.call(1, 2) #=> #<Proc>
proc2.call(3) #=> [1,2,3]
def vararg(*args)
args
end
proc = self.method(:vararg).curry(4)
proc2 = proc.call(:x) #=> #<Proc>
proc3 = proc2.call(:y, :z) #=> #<Proc>
proc3.call(:a) #=> [:x, :y, :z, :a]
hash → integer
메서드 객체에 대응하는 해시 값을 돌려줘요. Object#hash도 참고하세요.
inspect → string
기반 메서드의 사람이 읽기 좋은 설명을 돌려줘요. to_s로도 부를 수 있어요.
"cat".method(:count).inspect #=> "#<Method: String#count(*)>"
(1..3).method(:map).inspect #=> "#<Method: Range(Enumerable)#map()>"
뒤의 경우 설명에 원래 메서드의 "주인"(Range에 include된 Enumerable 모듈)이 포함돼요. inspect는 가능할 때 메서드 인자 이름(호출 시퀀스)과 소스 위치도 제공해요. 인자 정의의 ...는 인자가 선택적(기본값이 있음)임을 뜻해요. C로 정의된 메서드(언어 핵심과 확장)는 위치와 인자 이름을 추출할 수 없어서, 임의 개수 인자를 뜻하는 *나 어떤 위치 인자를 뜻하는 _ 형태의 일반 정보만 제공돼요.
"cat".method(:count).inspect #=> "#<Method: String#count(*)>"
"cat".method(:+).inspect #=> "#<Method: String#+(_)>"
name → symbol
메서드의 이름을 돌려줘요.
original_name → symbol
메서드의 원래 이름을 돌려줘요. 별칭(alias)으로 만들어진 메서드에서 원래 이름을 알아낼 때 유용해요.
class C
def foo; end
alias bar foo
end
C.instance_method(:bar).original_name # => :foo
owner → class_or_module
이 메서드가 정의된 클래스나 모듈을 돌려줘요. 다시 말해, 메서드가 제거/미정의/교체되지 않는 한 다음이 성립해요. (메서드가 private면 instance_methods 대신 private_instance_methods를 써요.)
meth.owner.instance_methods(false).include?(meth.name) # => true
(1..3).method(:map).owner #=> Enumerable
관련: Method#receiver.
parameters → array
이 메서드의 파라미터 정보를 돌려줘요.
def foo(bar); end
method(:foo).parameters #=> [[:req, :bar]]
def foo(bar, baz, bat, &blk); end
method(:foo).parameters #=> [[:req, :bar], [:req, :baz], [:req, :bat], [:block, :blk]]
def foo(bar, *args); end
method(:foo).parameters #=> [[:req, :bar], [:rest, :args]]
receiver → object
메서드 객체에 묶인 리시버를 돌려줘요.
(1..3).method(:map).receiver # => 1..3
source_location → [String, Integer, Integer, Integer, Integer]
메서드가 정의된 위치를 돌려줘요. 돌려받은 Array는 다음을 담아요. (1) Ruby 소스 파일명 (2) 정의가 시작되는 줄 번호 (3) 정의가 시작되는 열 번호 (4) 정의가 끝나는 줄 번호 (5) 정의가 끝나는 열 번호. 메서드가 Ruby로 정의되지 않았다면(네이티브) nil을 돌려줘요.
super_method → method
super를 쓸 때 호출될 슈퍼클래스의 Method를 돌려줘요. 슈퍼클래스에 그런 메서드가 없으면 nil이에요.
to_proc → proc
이 메서드에 대응하는 Proc 객체를 돌려줘요.
to_s → string
기반 메서드의 사람이 읽기 좋은 설명을 돌려줘요. inspect의 별칭이에요.
unbind → unbound_method
meth를 현재 리시버에서 분리해요. 결과 UnboundMethod는 같은 클래스의 새 객체에 다시 묶을 수 있어요(UnboundMethod 참고).