r2 - 2013-05-29 - 01:33:28 - LuzLunaYou are here:Foswiki>Docs Web>메타객체프로토콜(MOP)입문1
editattachsettingsACLs

add
print raw
historyrenamedelete
children new

본 문서는 http://gihyo.jp/dev/serial/01/perl-hackers-hub/001301 을 번역한 문서입니다.


메타객체프로토콜(MOP)입문1 | 메타객체프로토콜(MOP)입문2 | 메타객체프로토콜(MOP)입문3

본 연재에서는 현직 Perl 해커가 번갈아가면서 집필합니다. 이번에는 Perl 5에서 고급 객체 지향을 실현하기위한 프레임 워크 Moose 등의 개발에 참여하는 Shawn Moore (sartak) 씨와 Japan Perl Association의 이사 인 마키 다이스케(lestrrat) 씨가 "메타 개체 프로토콜(MOP)"에 대해 설명합니다.

메타 객체 프로토콜 (MOP)은

다양한 프로그래밍 언어가 객체 지향 기능을 제공하지만 개체의 구조를 세부적 열람하거나 기본 동작을 확장하는 것까지 할 수있는 언어는 많지 않습니다.

이러한 작업을 수행하려면 "메타 개체 프로토콜"(이후 : MOP - MetaObject Protocol)라는 기술을 사용합니다. MOP는 개체의 메서드와 속성 등 내부 구조 자체를 객체로 표현하는 방법입니다. Perl뿐만 아니라 다양한 프로그래밍 언어로 구현되어 있습니다.

MOP는 내부에 은폐 된 메타 정보뿐만 아니라, 클래스 메소드 역할 등을 일반적인 객체 군으로 표현하여 개체 정의의 모든 부분을 조작 할 수 있습니다. 게다가 개체를 이용하고 있기 때문에 해당 클래스를 상속하여 쉽게 동작을 변경할 수 있습니다. 또한 이외에도 동적 개체를 쉽게 만들 수있으며 그 외에도 다양한 편리한 이용법이 있습니다

MOP을 이용하는 것으로, 개체 지향 원리를 희생하지 말고 클래스 구현의 유연성을 올리는 혜택을 얻을 수 있습니다. MOP를 통해 얻어진 유연성은 개체 지향이라는 개념의 설계자들이 생각하지 못했던 기능의 추가도 가능하게 해 줍니다.

MOP의 기본

그러면 MOP의 거동을 살펴 보겠습니다. 먼저 MOP를 사용하여 클래스를 정의 해 보겠습니다. 본 글에서는 편의상 모든 MOP 기반 클래스 빌더 인 Class::MOPMoose 을 사용하지만 이들과 호환 API를 구현하는 도구라면 동등할 수 있습니다.

Class :: MOP 설치

Class :: MOP는 아래의 Moose에 포함 된 모듈입니다. Moose을 설치하려면 cpanm 및 cpan 명령을 사용하여 CPAN에서 설치합니다.

$ cpanm Moose

cpanm가 설치되어 있지 않으면 다음과 같이 설치할 수 있습니다.

$ curl -Lk http://xrl.us/cpanm | perl - Moose

클래스의 정의

Class :: MOP를 사용하여 클래스를 정의하려면 Class :: MOP :: Class 객체의 인스턴스를 생성합니다.

이 개체는 "메타 클래스"라고 어떤 클래스를 표현합니다. 이 메타 클래스에 대한 작업을 수행 할 때 메서드 및 속성 정의도 가능합니다 ( 목록 1 ).

목록 1 MOP의 클래스의 정의

use strict;
use Class::MOP;

#(1)클래스 만들기
my$meta=Class::MOP::Class->create('Person');

#(2)어트리뷰트 추가
$meta->add_attribute(
    'name',
    accessor=>'name',
);

#(3)메서드를 추가합니다
$meta->add_method(describe=>sub{
    my$self=shift;
    my$name=$self->name;
    print"$name";
});

#(4)개체 인스턴스 생성
my$object=$meta->new_object(name=>"Shawn");
$object->describe();;

먼저 목록 1 (1) 에서 Person이라는 클래스의 메타 클래스 인스턴스를 생성합니다. create 로 작성하는 클래스 이름을 인수로 전달합니다.

목록 1 (2) 에서 name 이라는 속성을 정의합니다. accessor => 'name' 이 속성에 액세스하기위한 접근 이름을 지정하여 읽기 및 쓰기 모두 할 수있는 접근자가 생성됩니다. 읽기 전용, 쓰기 전용의 경우 reader , writer 등을 지정합니다.

목록 1 (3) 에서 클래스에 메서드를 추가합니다. 여기에서는 단순히 객체 인스턴스의 정보를 출력하는 메소드인 describe() 를 정의했습니다.

지금까지 대충 클래스 정의했기 때문에 개체 인스턴스를 생성합니다. 여기에는 일반 new() 생성자가 아닌 MOP의 인스턴스 생성의 창구 인 new_object () 를 사용합니다. 목록 1 (4) 는 new_object() 를 사용하고 필요한 인수를 전달하여 객체를 생성합니다.

클래스의 상속

클래스를 상속하여 확장 할 경우 어떻게 할 수 있을까?

목록 2 에 Person의 하위 클래스로 Employee (직원)을 만듭니다.

목록 2 MOP의 서브 클래스의 정의

use strict;
use Class::MOP;
use Person;

#(1)클래스 만들기
my$meta=Class::MOP::Class->create('Employee');

#(2)부모 클래스의 지정
$meta->superclasses('Person');

$meta->add_attribute(
    'employer',
    accessor=>'employer',
);

#(3)메서드를 재정의
$meta->add_method(
    'describe',
    sub{
        my$self=shift;
        my$company=$self->employer->name;
        my$name=$self->name;
        print"소속$company, 사원 이름$name";

        #다음은 부모 클래스에 맡겨 줘
        $self->next::method();;
    }
);

먼저 목록 2 (1) 에서 Person 때와 마찬가지로 메타 클래스 인스턴스를 생성합니다.

부모 클래스의 지정은 superclasses라는 메서드에 부모 클래스 명을 지정하여 구현할 수 있습니다. 목록 2 (2) 에서는 Person을 부모 클래스로 상속 관계를 선언합니다. 이 메서드 호출에서 기존의 Perl에서 필요했던 @ ISA 관리를 실시해줍니다.

목록 2 (3) 에서는 add_method() 를 Employee 클래스에서도 호출하여 Person에 정의 된 메서드를 재정의하고 있습니다. 부모 클래스의 메소드를 호출 할 때 Class::MOP / Moose는 mro.pm 를 사용하고 있으므로, SUPER:: 기법이 아닌 next::method 를 사용하고 있습니다.

메소드 수정자

Class::MOP는 앞의 메서드 재정의 외에도 "메소드 수정자"라는 구조를 사용할 수 있으므로 일반 메소드의 앞뒤에 다른 메서드를 연결하실 수 있습니다.

구체적으로는 목록 3 과 같이 describe()에 메서드 모디파이어 (메소드 실행 후크)를 등록하여 부모 클래스의 메소드 실행 전에 목록 2 (3) 과 유사한 정보를 출력하도록 지정할 수 있습니다.

목록 3 메소드 수정 자

$meta->add_before_method_modifier(
    'describe',
    sub{
        my$self=shift;
        my$company=$self->employer->name;
        print"소속$company, 사원 이름";
    },
);

클래스 조사

메타 클래스를 이용함으로써 모든 클래스의 다양한 정보를 검색할 수 있습니다. 실제로 방금 만든 Employee클래스의 정보를 알아봅시다(목록 4).

목록 4 MOP에서 클래스를 조사

use strict;
use Employee;

#(1)메타 클래스의 취득
my$class=Employee->meta;

#"Employee"
print$class->name,"\n";
#"Person"
print$class->superclasses,"\n";

#(2)메타 어트리뷰트
my$attribute=
    $class->find_attribute_by_name('employer');
my$accessor=$attribute->accessor;

#(3)메타 메서드
my$method=$class->find_method_by_name($accessor);

#"employer"
print$method->name,"\n";
#"Employee::employer"
print$method->fully_qualified_name,"\n";

먼저 목록 4 (1) 에서 Employee의 메타 클래스를 얻기 위해 Employee->meta 를 호출합니다. MOP을 사용하여 생성 된 클래스는 자동으로 클래스 메소드가 정의되어 메타 클래스를 얻을 수 있도록되어 있습니다.

목록 4 (2) 에서 find_attribute_by_name 를 사용하여 속성을 표현하는 객체 "메타 속성"을 가져옵니다. 메타 속성은 해당 속성 정보를 포함하며 형식 제약 조건의 확인이나 속성의 기본값을 생성하는 로직 관리 등을 수행합니다.

목록 4 (3) 에서는 속성 접근자를 나타내는 "메타 메서드"를 검색합니다 (엄밀하게는이 메타 메소드 인 Class::MOP::Method가 아니라 접근자를 표현하기위한 서브 클래스의 Class::MOP::Method::Accessor입니다). 이 개체는 모든 속성의 접근인지 등의 정보를 포함하고 있으며, 쓰기 · 읽기 접근 용 메소드의 코드를 생성 할 수 있습니다.

이러한 메타 클래스 메타 속성과 메타 메서드 등을 "메타 레이어"일반 클래스를 "기본 레이어"이라고합니다. MOP의 가장 큰 특징 중 하나는 일반적으로 계층의 클래스 정의에 관련된 다양한 정보가 메타레이어에서 취득 · 확인할 수있다는 것 입니다.


메타객체프로토콜(MOP)입문1 | 메타객체프로토콜(MOP)입문2 | 메타객체프로토콜(MOP)입문3

저자소개
Shawn M Moore

통칭 Sartak. 보스턴 거주. Infinity Interactive Inc. 소속.

Moose 같은 도구의 개발 멤버로서 활약하는 것 외에 YAPC 등에서의 강연도 다수. 큰 친일파로 알려짐 YAPC::Asia Tokyo에도 자주 방문하고있다.

URL : http://sartak.org

Twitter : @ sartak
마키 다이스케 (마키 다이스케)

브라질, 미국에서 자라, Network Appliance Inc. 근무 후 귀국. 도어 (주)와 기업 등을 거쳐 현재 Japan Perl Association 대​​표 이사, NHN Japan 소속.

2011 년 White Camel Award 수상. 저작권에 "현대 Perl 입문"(쇼 에이 출판사)가있다.

Twitter : @lestrrat

주의: 저작권은 원 저자에게 있으며 WEB+DB PRESS Vol.67 으로 출판된 내용입니다. 몰래 번역한거라 그럴일은 없겠지만 혹시라도 상업적인 용도로 사용하시면 99% 문제가 생긴다는 사실을 미리 알려드립니다. -- LuzLuna - 2013-05-24
Topic revision: r2 - 2013-05-29, LuzLuna
 
This site is powered by FoswikiCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding Foswiki? Send feedback