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 참고).