Perl 객체? Python과 비교하며 감을 잡아보자.

aero의 이미지

KDLP에서 글들을 읽다가 보면 Perl에서는 객체지향하는데 맞지않다,왠지 어려울것이다등
FUD(Fear, uncertainty and doubt)가 퍼져 있음을 느낍니다.
http://kldp.org/node/77727#comment-366422

그래서 가장 간단한 객체하나를 예를들어 Perl,Python을 비교해보고자 합니다.
Python으로 OOP프로그래밍을 입문하신 분들이 더 많은거 같으니 먼저

Python버젼

Person.py

#!/usr/bin/env python
 
class Person:
    def __init__(self, name, height):
        self.name = name
        self.height = height
 
    def sayGreeting(self):
        print "Hello!  My name is", self.name,
        print "I am", self.height, "feet tall!"
 
 
frodo = Person("Saruman", 9)  # (객체생성) 내부적으로 Person이 __init__의 첫번째 인자로 넘어간다.
frodo.sayGreeting()           # frodo가 내부적으로 sayGreeting의 첫번째 인자로 넘어간다.
Person.sayGreeting(frodo)     # 윗줄을 풀어쓰면 다음과 같다. 똑같은 결과가 나옴

다음은 Perl 버젼

Person.pl

#!/usr/bin/env perl
use strict;
use warnings;
 
package Person;
 
sub new {
    my ($class,$name,$height) = @_;               # @_는  Perl에서 넘겨준 parameter들을 담고 있는 배열을 가르키는 특수변수
    my $self = { name=>$name, height=>$height };  # $self라는 hash reference를 만든다.
    bless $self, $class;                          # 만들어진 $self를 넘어온 $class(Person)이름의 객체로 만들어준다.
    return $self;                                 # 객체를 리턴한다.
}
 
sub sayGreeting {
    my $self = shift;
    print "Hello!  My name is $self->{name}. ";
    print "I am $self->{height} feet tall!\n";
}
 
 
package main;
 
my $sharky = new Person("Saruman", 9);            #(객체생성) 내부적으로 Person이 new의 첫번째 인자로 전달된다.
# my $sharky = Person->new("Saruman", 9);         #또 다른 객체 생성방법
# my $sharky = Person::new("Person","Saruman",9); #풀어쓰면 다음과 같다. (이상 3줄은 똑같은 기능을 함)
 
$sharky->sayGreeting();                           #내부적으로 $sharky가 sayGreeting의 첫번째 인자로 전달된다.
Person::sayGreeting($sharky);                     #윗줄을 풀어쓰면 다음과 같다. 똑같은 결과가 나옴

보면 서로 다르면서도 비슷한 부분이 있음을 느끼실겁니다.

Perl OOP에 대해 더 깊이 공부하시고 싶은분들은
http://kldp.org/node/77727#comment-366964
을 참조하세요.

Forums: 
aero의 이미지

Perl 5의 객체지향은 약간은 번거로운 작업과 Perl이 자유도가 높은 언어적 특성때문에 짜는 사람마다 다른 형태로 짜여질 소지가 좀 있습니다.
(위에서 실제로 객체를 초기화 하는 new 함수는 이름을 꼭 new로 써야될 필요도 없으며 $self,$class등도 이름을 마음대로 지정해도 됩니다. 다만 타 객체지향언어에서 많이 쓰이는것과 비슷하게 이름 붙인것이지요..)
따라서 Perl 5에도 Perl 6의 발전된 객체지향이 나오기전에 이를 개선하고자하는 노력이 계속되어 현재는 Moose (A complete modern object system for Perl 5 )가 등장하여
참고: http://search.cpan.org/~stevan/Moose-0.17/
메타 클래스 시스템같은 현대적 객체시스템을 사용가능 합니다.
이것은 개발되고 있는 Perl6의 객체지향과 유사한 형태로 차후 부드러운 패러다임 시프트를 가능하게 한다고 합니다.

그럼 어떻게 생겼는지 한 번 봅시다.

#!/usr/bin/env perl
use strict;
use warnings;
 
package Person;
use Moose;
 
has 'name' => (is => 'ro', isa => 'Str');
has 'height' => (is => 'ro', isa => 'Int');
 
sub sayGreeting {
    my $self = shift;
    print "Hello!  My name is $self->{name}. ";
    print "I am $self->{height} feet tall!\n";
}
 
package main;
 
my $sharky = Person->new( name=>"Saruman", height=>9 );
$sharky->sayGreeting();

Python 못지않게 깔끔하고 오히려 더 간단해 보이지 않나요?
게다가 객체내부 인자들의 속성및 타입을 지정까지 할 수 있습니다.

klenui의 이미지

perl 객체는 전혀 몰랐습니다만, 올려주신 예제를 보니 한번에 알겠네요..
좋은 글 감사합니다.

aero의 이미지

보통 Python 같은 언어들은 만들때 부터 내세운것이 OOP라 입문 서적을 봐도 앞부분에 객체에 대한 예제를 들며 설명하지만 Perl서적들은 Perl 5이전 시절의 절차적프로그래밍 시절의 관성이 남아있어 OOP에 대해서는 잘 다루지 않습니다. 거기다 우리나라에서는 Perl의 OOP를 다룬 비교적 최신판 서적이나 문서는 번역된것이 없구요.

그래서 우리나라에서 Perl에서 OOP는 이미 외국에서는 Perl OOP를 널리 활용하고 일상적으로 쓰는데 비해
FUD의 상태에 놓여져 있었다고 보입니다.

저도 글을 쓰면서 일반적인 OOP 프로그래밍에 대한 개념이 있는 분이면 제가 보여드린 예제를 금방 이해할것이라고 생각했습니다.

위 예제만 이해하면 나머지 좀 더한 고급테크닉은 어렵지 않습니다. 제가 올려드린 참고링크를 보고 살을 붙여가시면 됩니다. 저는 모든사람을 가로막고 있는 FUD에 휩싸인 그 첫 관문을 깨뜨리기 위해 이 글을 올린것이니까요. :)

서지원의 이미지

파이썬은 만들 때부터 OOP를 염두에 두고 만든 것이 아닙니다. 처음에는 class도 없다가 이후에 OOP와 관련된 기능들이 추가된 것입니다. self를 explicit하게 parameter로 넘기는 것도 언어 자체를 가장 최소로 바꾸면서 (혹은 implementation의 변경을 가능한 한 작게 유지하면서) OOP기능을 추가하기 위해서 그렇게 한 것이지요. less is more 철학과 관련이 있습니다. (less is more, Richard Garbriel로 구글 검색을 하면 그가 쓴 글이 나옵니다.;;)

글의 본래 내용과는 별로 상관은 없겠습니다.

gamdora의 이미지

펄*을 익히고 있는데 이런 글 너무 좋아요! >_<

익명사용자의 이미지

OOP라면 상속이 제일 중요한 예제일듯합니다만 그 부분이 빠져 있네요.

keedi의 이미지

상속은 extends를 사용하면 됩니다. 예제들을 보면 알 수 있으시겠지만,
원래의 펄 객체에서도 그렇듯이 다중 상속이 가능합니다.

Moose 모듈을 CPAN에서 설치 후 podbrowser 같은 곳에서 오프라인으로
읽을 수 있습니다. 또는 CPAN의 아래 주소에서 브라우져로 한번 만 읽어보셔도
대충 이해할 수 있을 것 같습니다~ :-)

http://search.cpan.org/~stevan/Moose-0.17/lib/Moose/Cookbook.pod

  package Point;
  use Moose;
 
  has 'x' => (isa => 'Int', is => 'ro');
  has 'y' => (isa => 'Int', is => 'rw');
 
  sub clear {
      my $self = shift;
      $self->{x} = 0;
      $self->y(0);    
  }
 
  package Point3D;
  use Moose;
 
  extends 'Point';
 
  has 'z' => (isa => 'Int');
 
  after 'clear' => sub {
      my $self = shift;
      $self->{z} = 0;
  };

---------------------------
Smashing Watermelons~!!
Whatever Nevermind~!!

----
use perl;

Keedi Kim

aero의 이미지

상속은 제가 윗글에도 말씀드렸다시피
-------------------------------------------
Perl OOP에 대해 더 깊이 공부하시고 싶은분들은
http://kldp.org/node/77727#comment-366964
을 참조하세요.
-------------------------------------------
첫 예제를 이해하셨고 OOP에 대한 개념이 있으신 분이라면 위 링크들을 보시면 상속,다형성등 OOP의 더 깊은 테크닉을 쉽게 이해하실 수 있을거라 생각해서 안 올렸습니다.

말 나온김에 상속예제도 하나 올려봅니다.
(이건 에러처리등이 빠진 간단한 본보기일 뿐입니다. 참고 링크의 문서를 보시면 더 세련된 테크닉을 배우실 수 있을겁니다. 보통 Perl에서 Package단위로 *.pm 파일로 분리하여 작성하고 use를 통해 로딩해서 쓰지만 저는 설명의 편의상 한 파일에 다 밀어넣는 방식으로 작성했습니다.)

이제 뭐는 왜 없냐 하지마세요 :) RTFM

#!/usr/bin/env perl
use strict;
use warnings;
 
package Person;
 
sub new {
    my ($class,$name,$height) = @_;
    my $self = { name=>$name, height=>$height };
    bless $self, $class;
    return $self;
}
 
sub sayGreeting {
    my $self = shift;
    print "Hello!  My name is $self->{name}. ";
    print "I am $self->{height} feet tall!\n";
}
 
# Person을 상속하는 Man 객체
package Man;
our @ISA = qw(Person);    # Person을 상속한다.
 
sub new {
    my $class = shift;
    my $self = $class->SUPER::new( shift, shift );  # 자식객체의 생성자를 호출한다.
    $self->{age} = shift || 0;                        # age 속성을 추가한다. 인자가 없으면 기본으로 0살
    bless $self, $class;
    return $self;
}
 
sub set_age {
    my ( $self, $age ) = @_;
    $self->{age} = $age;
    return $self->{age};
}
 
sub sayGreeting {
    my $self = shift;
    $self->SUPER::sayGreeting();
    print "I am $self->{age} years old.\n";
}
 
package main;
 
my $tom = new Man("Tom",3);
$tom->sayGreeting();
$tom->set_age(1);
$tom->sayGreeting();
 
my $bill = new Man("Bill", 1, 3);
$bill->sayGreeting();

결과

Hello!  My name is Tom. I am 3 feet tall!
I am 0 years old.
Hello!  My name is Tom. I am 3 feet tall!
I am 1 years old.
Hello!  My name is Bill. I am 1 feet tall!
I am 3 years old.

마침 Moose로 상속하는 예제는 keedi님이 위에 올려주셨네요. :)

aero의 이미지

1:1 비교를 하는게 가장 좋은것이라 생각되어
위 예제를 Moose로 똑같이 동작하도록 만들어 보겠습니다.
만들면서 저도 좀 같이 공부하구요~ :)

#!/usr/bin/env perl
use strict;
use warnings;
 
package Person;
use Moose;
 
has 'name' => (is => 'ro', isa => 'Str');
has 'height' => (is => 'ro', isa => 'Int');
 
sub sayGreeting {
	my $self = shift;
	print "Hello!  My name is $self->{name}. ";
	print "I am $self->{height} feet tall!\n";
}
 
package Man;
use Moose;
 
extends 'Person';
 
has 'age' => (is => 'rw', isa => 'Int', default=>0);
 
sub set_age {
    my ($self,%args) = @_;
    $self->{age} = $args{age};
    return $self->{age};
}
 
override 'sayGreeting' => sub {
	my $self = shift;
	super();
	print "I am $self->{age} years old.\n";
};
 
package main;
 
my $tom = new Man( name=>"Tom", height=>3);
$tom->sayGreeting();
$tom->set_age( age=>1 );
$tom->sayGreeting();
 
my $bill = new Man( name=>"Bill", height=>1, age=>3);
$bill->sayGreeting();

결과

Hello!  My name is Tom. I am 3 feet tall!
I am 0 years old.
Hello!  My name is Tom. I am 3 feet tall!
I am 1 years old.
Hello!  My name is Bill. I am 1 feet tall!
I am 3 years old.

doodoo의 이미지

광고성 글때문에 이렇게 좋은 글을 보게 되다니...
새옹지마(?) ....
감사합니다...펄에관한 글 잘 봤습니다...

hongminhee의 이미지

이 글을 보니, 저는 Perl을 거의 모릅니다만, Perl 5의 OOP가 Scheme 등에서와 같이 객체 모델을 직접 작성해서 사용할 수 있는 것이라면, 클래스 기반 말고 프로토타입 기반의 객체 모델도 사용할 수 있을 것 같습니다.

aero의 이미지

맞습니다.
Perl관련 책중에 Perl OOP에 설명한 다음 부분이 그 특징을 잘 말해줍니다.

Perl’s objectoriented
features are relatively basic and not compulsory. Perl takes a belt-and-braces approach to
object-oriented programming, espousing no particular object-oriented doctrine (of which there are
many), but permitting a broad range of different object-oriented styles. Despite this, and arguably
because of it, Perl is more powerful as an object-oriented language than it is often given credit for.
Many object-oriented languages take a much stricter line. Being strict is the entire point for
some languages. Java, for instance, requires that everything be an object, even the main application.
Other languages have very precise views about what kind of object model they support, how multiple
inheritance works, how public and private variables and methods are defined, how objects are
created, initialized, and destroyed, and so on. Perl’s disposition inherits much from languages like
Lisp, which combine a deliberately very simple syntax with the ability to extend it in almost any
direction. As such, Perl does not endorse any particular model of object-oriented programming,
which makes it both extremely flexible and highly disconcerting to programmers used to a different
object-oriented style.

프로토타입기반의 객체 모델도 있는걸로 보이네요.
Class::Prototyped http://search.cpan.org/dist/Class-Prototyped/lib/Class/Prototyped.pm
그리고 위에서 제가 언급한 Moose말고도
Perl CPAN에는 아주 다양한 객체모델을 지원하는 Class:: 계 모듈이 많습니다.

Survey of POOP Modules
http://www.perlmonks.org/?displaytype=print;node_id=556407

hongminhee의 이미지

오… 최근 Perl과 마주치는 일이 많은데 한번 공부해 봐야겠습니다.

익명 사용자의 이미지

Perl CPAN에는 아주 다양한 객체모델을 지원하는 Class:: 계 모듈이 많습니다.

같은 특징은 코드를 자기 마음대로 작성하려는 입장에서 보면 장점일지 모르지만
다른 사람이 만들어논 소스를 읽어야 하는 입장에서는 큰 단점이 될 것 같네요.

hongminhee의 이미지

저도 사실 그 생각을 하긴 했습니다만… 일장일단이 있는 거니까요. 다만 위에서 소개한 Moose가 거의 표준에 가까운 위치를 가지고 있는 것 같은데, 그렇다면 큰 문제는 없을 것 같습니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.