PERL의 객체 지향 프로그래밍
우리는 이미 Perl 및 Perl 익명 배열 및 해시의 참조를 연구했습니다. Perl의 객체 지향 개념은 참조와 익명 배열 및 해시를 기반으로합니다. Object Oriented Perl의 기본 개념을 배우기 시작하겠습니다.
개체 기본 사항
Perl이 객체를 처리하는 방법의 관점에서 설명되는 세 가지 주요 용어가 있습니다. 용어는 객체, 클래스 및 방법입니다.
안 objectPerl 내에서는 자신이 속한 클래스를 알고있는 데이터 유형에 대한 참조 일뿐입니다. 객체는 스칼라 변수에 참조로 저장됩니다. 스칼라는 객체에 대한 참조 만 포함하기 때문에 동일한 스칼라는 서로 다른 클래스에 서로 다른 객체를 보유 할 수 있습니다.
ㅏ class Perl 내에는 개체를 만들고 조작하는 데 필요한 해당 메서드가 포함 된 패키지가 있습니다.
ㅏ methodPerl 내에는 패키지로 정의 된 서브 루틴이 있습니다. 메서드에 대한 첫 번째 인수는 메서드가 현재 개체 또는 클래스에 영향을 미치는지 여부에 따라 개체 참조 또는 패키지 이름입니다.
Perl은 bless() 함수는 궁극적으로 객체가되는 참조를 반환하는 데 사용됩니다.
클래스 정의
Perl에서 클래스를 정의하는 것은 매우 간단합니다. 클래스는 가장 단순한 형태의 Perl 패키지에 해당합니다. Perl에서 클래스를 만들기 위해 먼저 패키지를 빌드합니다.
패키지는 사용자 정의 변수 및 서브 루틴의 자체 포함 된 단위로, 반복해서 다시 사용할 수 있습니다.
Perl 패키지는 Perl 프로그램 내에서 별도의 네임 스페이스를 제공하여 서브 루틴과 변수를 다른 패키지의 것과 충돌하지 않도록 유지합니다.
Perl에서 Person이라는 클래스를 선언하려면-
package Person;
패키지 정의의 범위는 파일의 끝까지 또는 다른 패키지 키워드를 만날 때까지 확장됩니다.
개체 생성 및 사용
클래스 (객체)의 인스턴스를 생성하려면 객체 생성자가 필요합니다. 이 생성자는 패키지 내에 정의 된 메서드입니다. 대부분의 프로그래머는이 객체 생성자 메서드의 이름을 new로 선택하지만 Perl에서는 어떤 이름도 사용할 수 있습니다.
Perl에서는 모든 종류의 Perl 변수를 객체로 사용할 수 있습니다. 대부분의 Perl 프로그래머는 배열 또는 해시에 대한 참조를 선택합니다.
Perl 해시 참조를 사용하여 Person 클래스에 대한 생성자를 생성 해 보겠습니다. 객체를 만들 때 객체 참조를 반환하는 패키지 내의 서브 루틴 인 생성자를 제공해야합니다. 개체 참조는 패키지의 클래스에 대한 참조를 축복하여 생성됩니다. 예를 들면-
package Person;
sub new {
my $class = shift;
my $self = {
_firstName => shift,
_lastName => shift,
_ssn => shift,
};
# Print all the values just for clarification.
print "First Name is $self->{_firstName}\n";
print "Last Name is $self->{_lastName}\n";
print "SSN is $self->{_ssn}\n";
bless $self, $class;
return $self;
}
이제 객체를 만드는 방법을 살펴 보겠습니다.
$object = new Person( "Mohammad", "Saleem", 23234345);
클래스 변수에 값을 할당하지 않으려면 생성자에서 간단한 해시를 사용할 수 있습니다. 예를 들면-
package Person;
sub new {
my $class = shift;
my $self = {};
bless $self, $class;
return $self;
}
방법 정의
다른 객체 지향 언어에는 프로그래머가 객체 데이터를 직접 변경하지 못하도록 데이터 보안 개념이 있으며 객체 데이터를 수정하는 접근 자 메서드를 제공합니다. Perl에는 개인 변수가 없지만 헬퍼 메소드의 개념을 사용하여 오브젝트 데이터를 조작 할 수 있습니다.
사람의 이름을 얻기 위해 도우미 메서드를 정의하자-
sub getFirstName {
return $self->{_firstName};
}
사람의 이름을 설정하는 또 다른 도우미 기능-
sub setFirstName {
my ( $self, $firstName ) = @_;
$self->{_firstName} = $firstName if defined($firstName);
return $self->{_firstName};
}
이제 완전한 예제를 살펴 보겠습니다 : Keep Person 패키지와 도우미 함수를 Person.pm 파일에 저장합니다.
#!/usr/bin/perl
package Person;
sub new {
my $class = shift;
my $self = {
_firstName => shift,
_lastName => shift,
_ssn => shift,
};
# Print all the values just for clarification.
print "First Name is $self->{_firstName}\n";
print "Last Name is $self->{_lastName}\n";
print "SSN is $self->{_ssn}\n";
bless $self, $class;
return $self;
}
sub setFirstName {
my ( $self, $firstName ) = @_;
$self->{_firstName} = $firstName if defined($firstName);
return $self->{_firstName};
}
sub getFirstName {
my( $self ) = @_;
return $self->{_firstName};
}
1;
이제 employee.pl 파일의 Person 객체를 다음과 같이 사용합니다.
#!/usr/bin/perl
use Person;
$object = new Person( "Mohammad", "Saleem", 23234345);
# Get first name which is set using constructor.
$firstName = $object->getFirstName();
print "Before Setting First Name is : $firstName\n";
# Now Set first name using helper function.
$object->setFirstName( "Mohd." );
# Now get first name set by helper function.
$firstName = $object->getFirstName();
print "Before Setting First Name is : $firstName\n";
위의 프로그램을 실행하면 다음과 같은 결과가 생성됩니다.
First Name is Mohammad
Last Name is Saleem
SSN is 23234345
Before Setting First Name is : Mohammad
Before Setting First Name is : Mohd.
계승
객체 지향 프로그래밍에는 상속이라는 매우 훌륭하고 유용한 개념이 있습니다. 상속은 단순히 부모 클래스의 속성과 메서드를 자식 클래스에서 사용할 수 있음을 의미합니다. 따라서 동일한 코드를 반복해서 작성할 필요가 없으며 부모 클래스를 상속 할 수 있습니다.
예를 들어, Person에서 상속되는 Employee 클래스를 가질 수 있습니다. 직원이 사람이기 때문에이를 "isa"관계라고합니다. Perl에는이를 돕기위한 특수 변수 @ISA가 있습니다. @ISA는 (메소드) 상속을 관리합니다.
다음은 상속을 사용하는 동안 고려해야 할 중요한 사항입니다.
Perl은 지정된 객체의 클래스에서 주어진 메소드 또는 속성, 즉 변수를 검색합니다.
Perl은 개체 클래스의 @ISA 배열에 정의 된 클래스를 검색합니다.
1 단계 또는 2 단계에서 메소드가 발견되지 않으면 Perl은 @ISA 트리에서 발견되는 경우 AUTOLOAD 서브 루틴을 사용합니다.
여전히 일치하는 메서드를 찾을 수없는 경우 Perl은 표준 Perl 라이브러리의 일부로 제공되는 UNIVERSAL 클래스 (패키지) 내에서 메서드를 검색합니다.
메서드가 여전히 발견되지 않으면 Perl은 포기하고 런타임 예외를 발생시킵니다.
따라서 Person 클래스에서 메서드와 특성을 상속 할 새 Employee 클래스를 만들려면 다음과 같이 코딩하면됩니다.이 코드를 Employee.pm에 유지합니다.
#!/usr/bin/perl
package Employee;
use Person;
use strict;
our @ISA = qw(Person); # inherits from Person
이제 Employee 클래스에는 Person 클래스에서 상속 된 모든 메서드와 속성이 있으며 다음과 같이 사용할 수 있습니다. 테스트를 위해 main.pl 파일을 사용합니다.
#!/usr/bin/perl
use Employee;
$object = new Employee( "Mohammad", "Saleem", 23234345);
# Get first name which is set using constructor.
$firstName = $object->getFirstName();
print "Before Setting First Name is : $firstName\n";
# Now Set first name using helper function.
$object->setFirstName( "Mohd." );
# Now get first name set by helper function.
$firstName = $object->getFirstName();
print "After Setting First Name is : $firstName\n";
위의 프로그램을 실행하면 다음과 같은 결과가 생성됩니다.
First Name is Mohammad
Last Name is Saleem
SSN is 23234345
Before Setting First Name is : Mohammad
Before Setting First Name is : Mohd.
메서드 재정의
자식 클래스 Employee는 부모 클래스 Person의 모든 메서드를 상속합니다. 그러나 자식 클래스에서 해당 메서드를 재정의하려면 자체 구현을 제공하여 수행 할 수 있습니다. 하위 클래스에 추가 함수를 추가하거나 상위 클래스에있는 기존 메서드의 기능을 추가 또는 수정할 수 있습니다. 다음과 같이 수행 할 수 있습니다. Employee.pm 파일을 수정합니다.
#!/usr/bin/perl
package Employee;
use Person;
use strict;
our @ISA = qw(Person); # inherits from Person
# Override constructor
sub new {
my ($class) = @_;
# Call the constructor of the parent class, Person.
my $self = $class->SUPER::new( $_[1], $_[2], $_[3] );
# Add few more attributes
$self->{_id} = undef;
$self->{_title} = undef;
bless $self, $class;
return $self;
}
# Override helper function
sub getFirstName {
my( $self ) = @_;
# This is child class function.
print "This is child class helper function\n";
return $self->{_firstName};
}
# Add more methods
sub setLastName{
my ( $self, $lastName ) = @_;
$self->{_lastName} = $lastName if defined($lastName);
return $self->{_lastName};
}
sub getLastName {
my( $self ) = @_;
return $self->{_lastName};
}
1;
이제 main.pl 파일에서 Employee 개체를 다시 사용하여 실행 해 보겠습니다.
#!/usr/bin/perl
use Employee;
$object = new Employee( "Mohammad", "Saleem", 23234345);
# Get first name which is set using constructor.
$firstName = $object->getFirstName();
print "Before Setting First Name is : $firstName\n";
# Now Set first name using helper function.
$object->setFirstName( "Mohd." );
# Now get first name set by helper function.
$firstName = $object->getFirstName();
print "After Setting First Name is : $firstName\n";
위의 프로그램을 실행하면 다음과 같은 결과가 생성됩니다.
First Name is Mohammad
Last Name is Saleem
SSN is 23234345
This is child class helper function
Before Setting First Name is : Mohammad
This is child class helper function
After Setting First Name is : Mohd.
기본 자동 로딩
Perl은 다른 프로그래밍 언어에서는 찾을 수없는 기능인 기본 서브 루틴을 제공합니다. 즉, 호출 된 함수를 정의하면AUTOLOAD(),그러면 정의되지 않은 서브 루틴에 대한 모든 호출은 AUTOLOAD () 함수를 자동으로 호출합니다. 누락 된 서브 루틴의 이름은이 서브 루틴 내에서 $ AUTOLOAD로 액세스 할 수 있습니다.
기본 자동로드 기능은 오류 처리에 매우 유용합니다. 다음은 AUTOLOAD를 구현하는 예입니다.이 기능을 원하는 방식으로 구현할 수 있습니다.
sub AUTOLOAD {
my $self = shift;
my $type = ref ($self) || croak "$self is not an object";
my $field = $AUTOLOAD;
$field =~ s/.*://;
unless (exists $self->{$field}) {
croak "$field does not exist in object/class $type";
}
if (@_) {
return $self->($name) = shift;
} else {
return $self->($name);
}
}
소멸자 및 가비지 컬렉션
이전에 객체 지향 프로그래밍을 사용하여 프로그래밍 한 적이 있다면 destructor사용이 끝나면 개체에 할당 된 메모리를 해제합니다. Perl은 객체가 범위를 벗어나는 즉시 자동으로이 작업을 수행합니다.
파일 닫기 또는 추가 처리를 처리해야하는 소멸자를 구현하려면 다음과 같은 특수 메서드를 정의해야합니다. DESTROY. 이 메서드는 Perl이 할당 된 메모리를 해제하기 직전에 개체에서 호출됩니다. 다른 모든 측면에서 DESTROY 메서드는 다른 메서드와 동일하며이 메서드 내에서 원하는 논리를 구현할 수 있습니다.
소멸자 메소드는 다음과 같은 경우에 자동으로 호출되는 DESTROY라는 멤버 함수 (서브 루틴)입니다.
- 개체 참조의 변수가 범위를 벗어날 때.
- 객체 참조의 변수가 정의되지 않은 경우.
- 스크립트가 종료 될 때
- Perl 인터프리터가 종료 될 때
예를 들어, 클래스에 다음 메소드 DESTROY를 넣을 수 있습니다.
package MyClass;
...
sub DESTROY {
print "MyClass::DESTROY called\n";
}
객체 지향 Perl 예제
다음은 Perl의 객체 지향 개념을 이해하는 데 도움이되는 또 다른 좋은 예입니다. 이 소스 코드를 perl 파일에 넣고 실행하십시오.
#!/usr/bin/perl
# Following is the implementation of simple Class.
package MyClass;
sub new {
print "MyClass::new called\n";
my $type = shift; # The package/type name
my $self = {}; # Reference to empty hash
return bless $self, $type;
}
sub DESTROY {
print "MyClass::DESTROY called\n";
}
sub MyMethod {
print "MyClass::MyMethod called!\n";
}
# Following is the implemnetation of Inheritance.
package MySubClass;
@ISA = qw( MyClass );
sub new {
print "MySubClass::new called\n";
my $type = shift; # The package/type name
my $self = MyClass->new; # Reference to empty hash
return bless $self, $type;
}
sub DESTROY {
print "MySubClass::DESTROY called\n";
}
sub MyMethod {
my $self = shift;
$self->SUPER::MyMethod();
print " MySubClass::MyMethod called!\n";
}
# Here is the main program using above classes.
package main;
print "Invoke MyClass method\n";
$myObject = MyClass->new();
$myObject->MyMethod();
print "Invoke MySubClass method\n";
$myObject2 = MySubClass->new();
$myObject2->MyMethod();
print "Create a scoped object\n";
{
my $myObject2 = MyClass->new();
}
# Destructor is called automatically here
print "Create and undef an object\n";
$myObject3 = MyClass->new();
undef $myObject3;
print "Fall off the end of the script...\n";
# Remaining destructors are called automatically here
위의 프로그램을 실행하면 다음과 같은 결과가 생성됩니다.
Invoke MyClass method
MyClass::new called
MyClass::MyMethod called!
Invoke MySubClass method
MySubClass::new called
MyClass::new called
MyClass::MyMethod called!
MySubClass::MyMethod called!
Create a scoped object
MyClass::new called
MyClass::DESTROY called
Create and undef an object
MyClass::new called
MyClass::DESTROY called
Fall off the end of the script...
MyClass::DESTROY called
MySubClass::DESTROY called