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