Lập trình hướng đối tượng trong PERL

Chúng tôi đã nghiên cứu các tham chiếu trong mảng và băm ẩn danh Perl và Perl. Khái niệm Hướng đối tượng trong Perl dựa rất nhiều vào các tham chiếu và mảng ẩn danh và hàm băm. Hãy bắt đầu tìm hiểu các khái niệm cơ bản về Perl hướng đối tượng.

Kiến thức cơ bản về đối tượng

Có ba thuật ngữ chính, được giải thích từ quan điểm về cách Perl xử lý các đối tượng. Các thuật ngữ là đối tượng, lớp và phương thức.

  • An objectbên trong Perl chỉ đơn thuần là một tham chiếu đến một kiểu dữ liệu biết nó thuộc về lớp nào. Đối tượng được lưu trữ dưới dạng tham chiếu trong một biến vô hướng. Bởi vì một đại lượng vô hướng chỉ chứa một tham chiếu đến đối tượng, cùng một đại lượng vô hướng có thể chứa các đối tượng khác nhau trong các lớp khác nhau.

  • A class bên trong Perl là một gói chứa các phương thức tương ứng cần thiết để tạo và thao tác các đối tượng.

  • A methodbên trong Perl là một chương trình con, được định nghĩa với gói. Đối số đầu tiên của phương thức là một tham chiếu đối tượng hoặc một tên gói, tùy thuộc vào việc phương thức ảnh hưởng đến đối tượng hiện tại hay lớp.

Perl cung cấp một bless() , được sử dụng để trả về một tham chiếu cuối cùng trở thành một đối tượng.

Xác định một lớp

Rất đơn giản để xác định một lớp trong Perl. Một lớp tương ứng với một Gói Perl ở dạng đơn giản nhất của nó. Để tạo một lớp trong Perl, trước tiên chúng ta xây dựng một gói.

Gói là một đơn vị chứa các biến và chương trình con do người dùng định nghĩa, có thể được sử dụng lại nhiều lần.

Perl Packages cung cấp một không gian tên riêng biệt trong chương trình Perl để giữ cho các chương trình con và biến độc lập khỏi xung đột với các chương trình con và biến trong các gói khác.

Để khai báo một lớp có tên là Person trong Perl, chúng ta thực hiện:

package Person;

Phạm vi của định nghĩa gói mở rộng đến cuối tệp hoặc cho đến khi gặp một từ khóa gói khác.

Tạo và sử dụng các đối tượng

Để tạo một thể hiện của một lớp (một đối tượng), chúng ta cần một phương thức khởi tạo đối tượng. Hàm tạo này là một phương thức được định nghĩa trong gói. Hầu hết các lập trình viên chọn đặt tên mới cho phương thức khởi tạo đối tượng này, nhưng trong Perl bạn có thể sử dụng bất kỳ tên nào.

Bạn có thể sử dụng bất kỳ loại biến Perl nào làm đối tượng trong Perl. Hầu hết các lập trình viên Perl chọn tham chiếu đến mảng hoặc hàm băm.

Hãy tạo phương thức khởi tạo cho lớp Person của chúng ta bằng cách sử dụng tham chiếu băm Perl. Khi tạo một đối tượng, bạn cần cung cấp một phương thức khởi tạo, là một chương trình con bên trong một gói trả về một tham chiếu đối tượng. Tham chiếu đối tượng được tạo bằng cách phù hợp với một tham chiếu đến lớp của gói. Ví dụ -

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;
}

Bây giờ Chúng ta hãy xem cách tạo một Đối tượng.

$object = new Person( "Mohammad", "Saleem", 23234345);

Bạn có thể sử dụng hàm băm đơn giản trong hằng số của mình nếu bạn không muốn gán bất kỳ giá trị nào cho bất kỳ biến lớp nào. Ví dụ -

package Person;
sub new {
   my $class = shift;
   my $self = {};
   bless $self, $class;
   return $self;
}

Phương pháp xác định

Các ngôn ngữ hướng đối tượng khác có khái niệm về bảo mật dữ liệu để ngăn lập trình viên thay đổi dữ liệu đối tượng trực tiếp và chúng cung cấp các phương thức truy cập để sửa đổi dữ liệu đối tượng. Perl không có các biến private nhưng chúng ta vẫn có thể sử dụng khái niệm phương thức helper để thao tác dữ liệu đối tượng.

Hãy xác định một phương thức trợ giúp để lấy tên của một người -

sub getFirstName {
   return $self->{_firstName};
}

Một chức năng trợ giúp khác để đặt tên của một người -

sub setFirstName {
   my ( $self, $firstName ) = @_;
   $self->{_firstName} = $firstName if defined($firstName);
   return $self->{_firstName};
}

Bây giờ chúng ta hãy xem xét ví dụ hoàn chỉnh: Gói Keep Person và các chức năng trợ giúp vào tệp 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;

Bây giờ hãy sử dụng đối tượng Person trong tệp worker.pl như sau:

#!/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";

Khi chúng ta thực hiện chương trình trên, nó tạo ra kết quả sau:

First Name is Mohammad
Last Name is Saleem
SSN is 23234345
Before Setting First Name is : Mohammad
Before Setting First Name is : Mohd.

Di sản

Lập trình hướng đối tượng có một khái niệm rất hay và hữu ích được gọi là kế thừa. Kế thừa đơn giản có nghĩa là các thuộc tính và phương thức của lớp cha sẽ có sẵn cho các lớp con. Vì vậy, bạn không cần phải viết đi viết lại cùng một đoạn mã, bạn chỉ có thể kế thừa một lớp cha.

Ví dụ, chúng ta có thể có một lớp Employee, kế thừa từ Person. Đây được gọi là mối quan hệ "isa" vì nhân viên là một người. Perl có một biến đặc biệt, @ISA, để trợ giúp việc này. @ISA quản lý (phương pháp) kế thừa.

Sau đây là những điểm quan trọng cần được xem xét khi sử dụng tính năng kế thừa:

  • Perl tìm kiếm lớp của đối tượng được chỉ định cho phương thức hoặc thuộc tính đã cho, tức là, biến.

  • Perl tìm kiếm các lớp được xác định trong mảng @ISA của lớp đối tượng.

  • Nếu không tìm thấy phương pháp nào trong bước 1 hoặc 2, thì Perl sẽ sử dụng chương trình con AUTOLOAD, nếu phương pháp đó được tìm thấy trong cây @ISA.

  • Nếu vẫn không tìm thấy phương thức phù hợp, thì Perl sẽ tìm kiếm phương thức trong lớp UNIVERSAL (gói) đi kèm như một phần của thư viện Perl chuẩn.

  • Nếu phương thức vẫn chưa được tìm thấy, thì Perl từ bỏ và đưa ra một ngoại lệ thời gian chạy.

Vì vậy, để tạo một lớp Employee mới sẽ kế thừa các phương thức và thuộc tính từ lớp Person của chúng ta, chúng ta chỉ cần viết mã như sau: Giữ mã này thành Employee.pm.

#!/usr/bin/perl

package Employee;
use Person;
use strict;
our @ISA = qw(Person);    # inherits from Person

Giờ đây, Lớp nhân viên có tất cả các phương thức và thuộc tính kế thừa từ lớp Người và bạn có thể sử dụng chúng như sau: Sử dụng tệp main.pl để kiểm tra nó -

#!/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";

Khi chúng ta thực hiện chương trình trên, nó tạo ra kết quả sau:

First Name is Mohammad
Last Name is Saleem
SSN is 23234345
Before Setting First Name is : Mohammad
Before Setting First Name is : Mohd.

Ghi đè phương pháp

Lớp con Employee kế thừa tất cả các phương thức từ lớp cha Person. Nhưng nếu bạn muốn ghi đè các phương thức đó trong lớp con của mình thì bạn có thể làm điều đó bằng cách đưa ra triển khai của riêng bạn. Bạn có thể thêm các chức năng bổ sung của mình trong lớp con hoặc bạn có thể thêm hoặc sửa đổi chức năng của một phương thức hiện có trong lớp cha của nó. Nó có thể được thực hiện như sau: sửa đổi tệp 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;

Bây giờ, hãy thử sử dụng đối tượng Employee trong tệp main.pl của chúng ta và thực thi nó.

#!/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";

Khi chúng ta thực hiện chương trình trên, nó tạo ra kết quả sau:

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.

Tự động tải mặc định

Perl cung cấp một tính năng mà bạn không thể tìm thấy trong bất kỳ ngôn ngữ lập trình nào khác: một chương trình con mặc định. Có nghĩa là, nếu bạn xác định một hàm được gọi làAUTOLOAD(),thì bất kỳ lệnh gọi nào đến các chương trình con không xác định sẽ tự động gọi hàm AUTOLOAD (). Tên của chương trình con bị thiếu có thể truy cập được trong chương trình con này là $ AUTOLOAD.

Chức năng tự động tải mặc định rất hữu ích để xử lý lỗi. Đây là một ví dụ để thực hiện AUTOLOAD, bạn có thể thực hiện chức năng này theo cách của mình.

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);
   }
}

Người tiêu hủy và thu gom rác

Nếu bạn đã lập trình bằng lập trình hướng đối tượng trước đây, thì bạn sẽ nhận thức được sự cần thiết phải tạo destructorđể giải phóng bộ nhớ được cấp cho đối tượng khi bạn sử dụng xong. Perl tự động thực hiện điều này cho bạn ngay khi đối tượng vượt ra khỏi phạm vi.

Trong trường hợp bạn muốn triển khai trình hủy của mình, công cụ này sẽ quan tâm đến việc đóng tệp hoặc thực hiện một số xử lý bổ sung thì bạn cần xác định một phương thức đặc biệt được gọi là DESTROY. Phương thức này sẽ được gọi trên đối tượng ngay trước khi Perl giải phóng bộ nhớ được cấp cho nó. Trong tất cả các khía cạnh khác, phương pháp DESTROY cũng giống như bất kỳ phương pháp nào khác và bạn có thể triển khai bất kỳ logic nào bạn muốn bên trong phương pháp này.

Phương thức hủy chỉ đơn giản là một hàm thành viên (chương trình con) có tên DESTROY, sẽ được gọi tự động trong các trường hợp sau:

  • Khi biến của tham chiếu đối tượng vượt ra khỏi phạm vi.
  • Khi biến của tham chiếu đối tượng là undef-ed.
  • Khi tập lệnh kết thúc
  • Khi trình thông dịch perl kết thúc

Ví dụ, bạn có thể chỉ cần đặt phương thức DESTROY sau vào lớp của mình:

package MyClass;
...
sub DESTROY {
   print "MyClass::DESTROY called\n";
}

Ví dụ Perl hướng đối tượng

Đây là một ví dụ hay khác, sẽ giúp bạn hiểu các khái niệm hướng đối tượng của Perl. Đặt mã nguồn này vào bất kỳ tệp perl nào và thực thi nó.

#!/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

Khi chúng ta thực hiện chương trình trên, nó tạo ra kết quả sau:

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