블로그 이미지
JEEN

서울에 사는 꽃청년의 IT찌질모험기

Rss feed Tistory
IT/Perl 2008.06.07 14:27

[ Perl ] Perl 로 OOP 하지 않겠나(요)? - Moose #3 - 형태에 관한 이야기

사용자 삽입 이미지

 지난번에는 Moose 의 상속에 대한 이야기를 해봤습니다. 사실 이것저것 빼먹고 가는 것이 많기 때문에, 개인적으로 좀 더 알아봐주셨으면 하는 심정이 있고, 좀 더 알아보자 라고 했을 때 좀 지루할 것 같아서... 일단 원리를 알고 쓰기보다는 쓰면서 원리를 알아가는 게 더 쉬운 방법인 것 같기도 합니다.

2008/06/02 - [IT/Perl] - [ Perl ] Perl 로 OOP 하지 않겠나(요)? - Moose #1-2

여기에서 isa 에 들어가는 형태에 대한 언급이 있었고, Int 에서 문자열 쓰면 에러난다는 등의 해서는 안될 짓에 대한 이야기를 한 적이 있습니다. 이번에는 형태에 대한 좀 더 자세한 이야기입니다.
 
package Me2day::Request;
use Moose;
use Moose::Util::TypeConstraints;

subtype 'URI' # 자기가 정의하고픈 형태의 이름
  => as 'Object'  # 계승한 형태
  => where { $_->isa('URI') }; # 형태의 Validation 체크 

has 'uri' => (is => 'rw', isa => 'URI');

1;

  일단 가장 간단한 예제를 주워와봤습니다. 이런 'URI' 같은 자신이 직접 형태를 정해줄 경우에는
use Moose::Util::TypeConstraints;
이 필수입니다.

 그런 다음에는 자기 나름대로 URI 이라는 형태를 지정해 줍니다.
subtype 'URI'
  => as 'Object'
  => where { $_->isa('URI') };
 이제 uri 접근자는 URI가 아니면 받아들일 수 없게 되어버립니다. 이 말인 즉슨...

 my $blah = Me2day::Request->new( 'uri' => 'http://jeen.tistory.com' );

 일 때, uri 의 값을 문자열인 http://jeen.tistory.com 으로 지정했습니다. 이러면 자신이 정의한 URI 의 타입에 맞지 않게 됩니다. URI 는 Object 이기를 기대하며, URI 모듈을 사용하기를 원하고 있죠. 그럼 이 입맛에 맞춰주면 됩니다.
 my $blah = Me2day::Request->new( 'uri' => URI->new('http://jeen.tistory.com') );

 그러면 이제 화를 내지 않는 우리의 Moooooose ~
 Moose 특유의 뿔 처럼 엄격함만을 강조하는 것이냐면, 그럴 수도 있습니다만, 여기서 더욱 유연하게 처리해줄 수 도 있습니다.
 coerce 'URI'
   => from 'Str'
   => via { URI->new($_) }
   => from 'Int'
   => via { blahblah... }
 coerce 를 사용하는 것입니다. 이러면 URI 속성을 사용하는 접근자에 문자열('Str') 이 올때에는 URI 모듈을 사용해서 부르게 됩니다. 이때는 여러 상속형태에 대해서 강제변경을 지정할 수 있습니다.

 여기서 중요한 것은 coerce 를 사용해서 강제로 형태변경할 경우에는 접근자에 옵션을 하나 더 추가해줘야 합니다.
has 'uri' => (is => 'rw', isa => 'URI', coerce => 1);
 이렇게 말이죠.

 전체코드입니다.

package Me2day::Request;
use Moose;
use Moose::Util::TypeConstraints; # 아래와 같은 일을 하려면 반드시!
use URI;

subtype 'URI' # 자기가 정의하고픈 형태의 이름
  => as 'Object'  # 계승한 형태
    => where { $_->isa('URI') }; # 형태의 Validation 체크

coerce 'URI' # 강제 형태변경
  => from 'Str' # 이런 타입이 오면
  => via { URI->new($_) };  # 이렇게 해줘야지.

has 'uri' => (is => 'rw', isa => 'URI', coerce => 1);

1;

my $blah = Me2day::Request->new ( uri => 'http://jeen.tistory.com' );
print $blah->uri."\n";  # http://jeen.tistory.com
print $blah->uri->scheme;  # http
 
  물론 uri 의 값은 URI->new('http://jeen.tistory.com') 를 써도 됩니다. 이건  subtype 에서 기본적으로 바라고 있는 값의 형태이기 때문입니다.

 이쯤에서 다른 예제를 불러오도록 하죠.
package Me2day::Request;
use Moose;
use Moose::Util::TypeConstraints;
use Digest::MD5;

subtype 'Encrypt'
    => as 'Str';

coerce 'Encrypt'
    => from 'Str'
    => via {
        my $nonce = sprintf "%08x", rand(16 ** 8);
        $nonce.Digest::MD5->new->add($nonce.$_)->hexdigest;
    };

has 'username' => (is => 'ro', isa => 'Str', required => 1);
has 'password' => (is => 'ro', isa => 'Encrypt', required => 1, coerce => 1);

1;

my $blah = Me2day->new ( username => 'jeen', password => '22830' );
print $blah->password; # 65dfb0a73f23368b4701a2435d8a64cabd26762b

 어떤 별 다른 차이점도 없습니다. Me2day의  인증키 생성을 위한 처리를 coerce 'Encrypt' 에 담아서,
password 값이 들어오면 자동으로 인증키를 만들고 그 값이 password 의 값으로 강제변경되는 것입니다. 위에서 언급을 빼먹었는데. coerce 를 사용하기 위해서는 subtype 이 지정되어 있어야 합니다.

 이상으로 Moose 의 형태변경에 대한 이야기를 마치겠습니다.
신고
TOTAL 483,672 TODAY 11

티스토리 툴바