Metamodel::MethodContainer 역할

Metamodel::MethodContainer 역할 (raku-type-metamodel-methodcontainer)

메서드를 저장하고 조회(introspect)하는 기능을 지원하는 메타객체 역할이에요. Raku의 메타객체 프로토콜(MOP)에서 클래스·역할·문법·열거형이 메서드를 담는 방식을 이 역할이 정의해요.

출처: Raku Docs - Metamodel::MethodContainer

주의: 이 역할은 Rakudo 구현의 일부예요. 언어 명세에는 포함되지 않는 부분이니, 라쿠도 내부를 건드릴 때나 참고하세요.

정의

role Metamodel::MethodContainer {}

역할, 클래스, 문법, 열거형은 모두 메서드를 가질 수 있어요. 이 역할은 그런 메서드를 저장하고 조회하는 API를 구현해요.

say .name for Int.^methods(:all);

# don't do that, because it changes type Int globally.
# just for demonstration purposes.
Int.^add_method('double', method ($x:) { 2 * $x });
say 21.double; # OUTPUT: «42␤»

위 코드는 ^add_methodIntdouble 메서드를 런타임에 추가해 21.double42가 되게 만드는 예시예요. 다만 주석에도 있듯이 이렇게 하면 전역 타입을 바꾸는 거라 실제 코드에서는 하면 안 돼요.

메서드

method add_method

method add_method($obj, $name, $code)

메타클래스에 이름 $name으로 메서드를 추가해요. 타입이 구성(compose)되기 이전에만 해야 해요.

method methods

method methods($obj, :$all, :$local)

클래스에서 쓸 수 있는 공개 메서드 목록을 돌려줘요(상위 클래스와 역할에서 물려받은 메서드 포함). 기본적으로는 Cool, Any, Mu에서 멈추는데, 정말 모든 메서드를 얻으려면 :all 부사를 쓰세요. :local을 지정하면 그 클래스에 직접 선언된 메서드만 돌려줘요.

class A {
    method x() { };
}

say A.^methods();                   # x
say A.^methods(:all);               # x infinite defined ...

돌려받는 목록은 Method 타입 객체들로 구성돼요. 이들을 통해 시그니처를 조회하고 호출할 수도 있어요. 다만 WHAT 같은 몇몇 조회용 유사 메서드는 문법 단계에서 처리돼서 이 목록에 나타나지 않아요. 부트스트랩 이유로 계속 그럴 가능성이 높아요.

method method_table

method method_table($obj --> Hash:D)

키가 메서드 이름이고 값이 Method인 해시를 돌려줘요. 키는 그 메서드를 호출할 때 쓰는 이름이지, 메서드가 스스로 아는 이름과 다를 수 있다는 점에 주의하세요.

method lookup

method lookup($obj, $name --> Method)

주어진 $name과 일치하는 첫 번째 Method 객체를 돌려줘요. 찾지 못하면 (Mu)를 돌려줘요. 검색은 $obj의 메서드 해석 순서(mro)를 따라 진행돼요. lookup은 조회용으로 쓰는 걸 전제로 해요. 실제로 호출할 수 있는 걸 찾으려면 find_method를 쓰는 게 낫죠.

say 2.5.^lookup("sqrt").raku;      # OUTPUT: «method sqrt (Rat $: *%_) ...␤»
say Str.^lookup("BUILD").raku;     # OUTPUT: «submethod BUILD (Str $: :$value = "", *%_ --> Nil) ...␤»
say Int.^lookup("does-not-exist"); # OUTPUT: «(Mu)␤»

find_methodlookup의 차이는 이래요. find_method는 매개변수적 역할에 기본 후보를 쓰지만 lookup은 그런 경우 예외를 던져요. 그리고 find_methodFALLBACK 메서드를 존중하지만 lookup은 그렇지 않아요.