Perl 객체지향
Perl에는 두 가지 다른 객체 지향 프로그래밍 구현이 있습니다.
하나는 익명 해시 테이블을 기반으로 합니다. 각 객체 인스턴스의 본질은 포인터 참조입니다. 익명의 해시 테이블에. 이 익명 해시 테이블에는 모든 인스턴스 속성이 저장됩니다.
두 번째는 클래스를 정의할 때 각 인스턴스 속성에 대한 배열을 생성하며, 각 객체 인스턴스의 본질은 이러한 배열에 대한 포인터입니다. 행 인덱스로. 이러한 배열에는 모든 인스턴스 속성이 저장됩니다.
객체 지향의 기본 개념
객체 지향에는 많은 기본 개념이 있는데 여기서는 객체, 클래스, 메서드 세 가지를 받아들입니다.
객체 : 객체는 클래스의 데이터 항목에 대한 참조입니다. .
클래스: 클래스는 객체 메서드를 제공하는 클래스가 포함된 Perl 패키지입니다.
메서드: 메서드는 Perl 서브루틴이고 클래스 이름은 첫 번째 매개변수입니다.
Perl은 bless() 함수를 제공합니다. bless는 객체를 생성하는 데 사용됩니다. Bless는 참조를 클래스 이름과 연결하고 참조를 반환하여 객체를 생성합니다.
클래스 정의
클래스는 단순한 패키지입니다.
패키지를 클래스로 사용할 수 있고, 패키지에 포함된 함수를 클래스의 메소드로 사용할 수 있습니다.
Perl 패키지는 독립적인 네임스페이스를 제공하므로 다른 패키지의 메서드와 변수 이름이 충돌하지 않습니다.
Perl 클래스의 파일 확장자는 .pm입니다.
다음으로 Person 클래스를 만듭니다.
package Person;
클래스의 코드 범위는 스크립트 파일의 마지막 줄이나 다음 패키지 키워드 앞에 도달합니다.
객체 생성 및 사용
클래스의 인스턴스(객체)를 생성하려면 생성자를 정의해야 하며, 대부분의 프로그램은 클래스 이름을 생성자로 사용합니다. 어떤 이름이든 가능합니다. Perl에서 사용됩니다.
다양한 Perl 변수를 Perl 객체로 사용할 수 있습니다. 대부분의 경우 참조 배열이나 해시를 사용합니다.
다음으로 Perl의 해시 참조를 사용하여 Person 클래스의 생성자를 만듭니다.
객체를 생성할 때 객체에 대한 참조를 반환하는 서브루틴인 생성자를 제공해야 합니다.
예제는 다음과 같습니다.
package Person; sub new { my $class = shift; my $self = { _firstName => shift, _lastName => shift, _ssn => shift, }; # 输出用户信息 print "名字:$self->{_firstName}\n"; print "姓氏:$self->{_lastName}\n"; print "编号:$self->{_ssn}\n"; bless $self, $class; return $self; }
다음으로 개체를 만듭니다.
$object = new Person( "小明", "王", 23234345);
메서드 정의
Perl 클래스의 메서드 이것은 단지 Perl 하위 프로그램일 뿐이며 멤버 함수라고도 알려진 프로그램일 뿐입니다.
객체 지향 Perl에서 Perl의 메서드 정의는 특별한 구문을 제공하지 않지만 메서드의 첫 번째 매개 변수가 참조되는 개체 또는 패키지라고 규정합니다.
Perl은 private 변수를 제공하지 않지만 보조 메소드를 통해 객체 데이터를 관리할 수 있습니다.
다음으로 이름을 가져오는 메서드를 정의합니다:
sub getFirstName { return $self->{_firstName}; }
다음과 같이 작성할 수도 있습니다:
sub setFirstName { my ( $self, $firstName ) = @_; $self->{_firstName} = $firstName if defined($firstName); return $self->{_firstName}; }
다음으로 Person.pm 파일의 코드를 다음과 같이 수정합니다. 다음과 같습니다:
#!/usr/bin/perl package Person; sub new { my $class = shift; my $self = { _firstName => shift, _lastName => shift, _ssn => shift, }; # 输出用户信息 print "名字:$self->{_firstName}\n"; print "姓氏:$self->{_lastName}\n"; print "编号:$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 스크립트 코드는 다음과 같습니다.
#!/usr/bin/perl use Person; $object = new Person( "小明", "王", 23234345); # 获取姓名 $firstName = $object->getFirstName(); print "设置前姓名为 : $firstName\n"; # 使用辅助函数设置姓名 $object->setFirstName( "小强" ); # 通过辅助函数获取姓名 $firstName = $object->getFirstName(); print "设置后姓名为 : $firstName\n";
위 프로그램을 실행한 후 출력 결과는 다음과 같습니다.
$ perl employee.pl 名字:小明 姓氏:王 编号:23234345 设置前姓名为 : 小明 设置后姓名为 : 小强
상속
Perl에서 클래스 메서드는 @ISA 배열을 통해 상속됩니다. 이 배열에는 다른 패키지(클래스)의 이름이 포함됩니다. 변수 상속은 명시적으로 설정되어야 합니다.
다중 상속은 @ISA 배열에 여러 클래스(패키지) 이름이 포함되어 있음을 의미합니다.
@ISA를 통해 메소드만 상속할 수 있으며, 데이터는 상속할 수 없습니다.
다음으로 Person 클래스를 상속하는 Employee 클래스를 만듭니다.
Employee.pm 파일의 코드는 다음과 같습니다.
#!/usr/bin/perl package Employee; use Person; use strict; our @ISA = qw(Person); # 从 Person 继承
이제 Employee 클래스에는 Person 클래스의 모든 메소드와 속성이 포함되어 있습니다. main.pl에 다음 코드를 입력합니다. 파일을 만들고 실행합니다:
#!/usr/bin/perl use Employee; $object = new Employee( "小明", "王", 23234345); # 获取姓名 $firstName = $object->getFirstName(); print "设置前姓名为 : $firstName\n"; # 使用辅助函数设置姓名 $object->setFirstName( "小强" ); # 通过辅助函数获取姓名 $firstName = $object->getFirstName(); print "设置后姓名为 : $firstName\n";
위 프로그램을 실행한 후 출력 결과는 다음과 같습니다.
$ perl main.pl 名字:小明 姓氏:王 编号:23234345 设置前姓名为 : 小明 设置后姓名为 : 小强
Method rewriting
위의 예에서 Employee 클래스는 Person 클래스이지만 Person 클래스인 경우 메서드가 요구 사항을 충족할 수 없으면 메서드를 다시 작성해야 합니다.
다음으로 Employee 클래스에 몇 가지 새로운 메서드를 추가하고 Person 클래스의 메서드를 재정의합니다.
#!/usr/bin/perl package Employee; use Person; use strict; our @ISA = qw(Person); # 从 Person 继承 # 重写构造函数 sub new { my ($class) = @_; # 调用父类的构造函数 my $self = $class->SUPER::new( $_[1], $_[2], $_[3] ); # 添加更多属性 $self->{_id} = undef; $self->{_title} = undef; bless $self, $class; return $self; } # 重写方法 sub getFirstName { my( $self ) = @_; # 这是子类函数 print "这是子类函数\n"; return $self->{_firstName}; } # 添加方法 sub setLastName{ my ( $self, $lastName ) = @_; $self->{_lastName} = $lastName if defined($lastName); return $self->{_lastName}; } sub getLastName { my( $self ) = @_; return $self->{_lastName}; } 1;
main.pl 파일에 다음 코드를 입력하고 실행합니다.
#!/usr/bin/perl use Employee; $object = new Employee( "小明", "王", 23234345); # 获取姓名,使用修改后的构造函数 $firstName = $object->getFirstName(); print "设置前姓名为 : $firstName\n"; # 使用辅助函数设置姓名 $object->setFirstName( "小强" ); # 通过辅助函数获取姓名 $firstName = $object->getFirstName(); print "设置后姓名为 : $firstName\n";
위 프로그램을 실행한 후 출력 결과는 다음과 같습니다.
$ perl main.pl 名字:小明 姓氏:王 编号:23234345 这是子类函数 设置前姓名为 : 小明 这是子类函数 设置后姓名为 : 小强
기본적으로 로드됨
현재 클래스에 있는 경우 현재 클래스의 모든 기본 클래스 및 UNIVERSAL 클래스를 요청할 방법을 찾을 수 없습니다. 이때 AUTOLOAD()라는 메소드를 다시 찾는다. AUTOLOAD가 발견되면 전역 변수 $AUTOLOAD를 호출하고 누락된 메서드의 정규화된 이름으로 설정합니다.
작동하지 않으면 Perl은 오류와 함께 실패합니다.
기본 클래스의 AUTOLOAD를 상속하지 않으려면 매우 간단합니다. 단 한 문장이면 됩니다:
sub AUTOLOAD;
소멸자와 가비지 수집
개체의 마지막 참조를 해제하면 개체가 자동으로 삭제됩니다.
파괴 중에 작업을 수행하려면 클래스에 "DESTROY"라는 메서드를 정의할 수 있습니다. 적절한 시간에 자동으로 호출되어 원하는 대로 추가 정리 작업을 수행합니다.
package MyClass; ... sub DESTROY { print "MyClass::DESTROY called\n"; }
Perl은 객체 참조를 다음과 같이 처리합니다. 전달된 유일한 인수는 DESTROY입니다. 이 참조는 읽기 전용이므로 $_[0]에 액세스하여 수정할 수 없습니다. (번역자 주: perlsub 참조) 그러나 객체 자체(예: "${$_[0]" 또는 "@{$_[0]}" 및 "%{$_[0]}" 등)은 여전히 쓰기 가능합니다.
소멸자가 반환되기 전에 개체 참조를 다시 축복하면 Perl은 소멸자가 반환된 후 다시 축복한 개체의 DESTROY 메서드를 호출합니다. 이를 통해 기본 클래스 또는 지정한 다른 클래스의 소멸자를 호출할 수 있습니다. DESTROY는 수동으로 호출할 수도 있지만 일반적으로 그렇게 할 필요는 없습니다.
현재 개체가 해제되면 현재 개체에 포함된 다른 개체도 자동으로 해제됩니다.
Perl 객체지향 예제
다음 예제를 통해 Perl의 객체지향 응용을 더 잘 이해할 수 있습니다.
#!/usr/bin/perl # 下面是简单的类实现 package MyClass; sub new { print "MyClass::new called\n"; my $type = shift; # 包名 my $self = {}; # 引用空哈希 return bless $self, $type; } sub DESTROY { print "MyClass::DESTROY called\n"; } sub MyMethod { print "MyClass::MyMethod called!\n"; } # 继承实现 package MySubClass; @ISA = qw( MyClass ); sub new { print "MySubClass::new called\n"; my $type = shift; # 包名 my $self = MyClass->new; # 引用空哈希 return bless $self, $type; } sub DESTROY { print "MySubClass::DESTROY called\n"; } sub MyMethod { my $self = shift; $self->SUPER::MyMethod(); print " MySubClass::MyMethod called!\n"; } # 调用以上类的主程序 package main; print "调用 MyClass 方法\n"; $myObject = MyClass->new(); $myObject->MyMethod(); print "调用 MySubClass 方法\n"; $myObject2 = MySubClass->new(); $myObject2->MyMethod(); print "创建一个作用域对象\n"; { my $myObject2 = MyClass->new(); } # 自动调用析构函数 print "创建对象\n"; $myObject3 = MyClass->new(); undef $myObject3; print "脚本执行结束...\n"; # 自动执行析构函数
위 프로그램을 실행하면 출력 결과는 다음과 같습니다:
调用 MyClass 方法 MyClass::new called MyClass::MyMethod called! 调用 MySubClass 方法 MySubClass::new called MyClass::new called MyClass::MyMethod called! MySubClass::MyMethod called! 创建一个作用域对象 MyClass::new called MyClass::DESTROY called 创建对象 MyClass::new called MyClass::DESTROY called 脚本执行结束... MyClass::DESTROY called MySubClass::DESTROY called