當前位置:首頁 » Perl » Perl麵向對象

Perl麵向對象

Perl麵向對象學習例子實例代碼教學 - 在我們了解perl的麵向對象的概念開始之前,讓我們了解引用和匿名數組和哈希表。

在我們了解perl的麵向對象的概念開始之前,讓我們了解引用和匿名數組和哈希表。

引用

  • 引用是完全像名稱所暗示的一樣,給另一個對象的引用或指針。

  • 有兩種類型的引用:符號和硬引用

  • 一個符號參考,使您能夠引用一個變量的名稱,使用另一個變量值。 例如,如果變量$foo的包含字符串“bar”,符號引用$foo的關聯變量$bar。

  • 一個硬引用是指在數據結構中包含的實際數據。

創建硬引用

一元反斜線運算符用於創建一個命名的變量或子程序,例如:

$foo = 'Bill';
$fooref = \$foo;

現在$fooref變量一個硬引用$foo的變量。你可以做同樣的與其他變量:

$array = \@ARGV;
$hash = \%ENV;
$glob = \*STDOUT;

要創建一個子程序:

sub foo { print "foo" };
$foosub = \&foo;

匿名數組

當你直接創建一個引用到一個數組 - 也就是說,冇有形成中間指定數組 - 您正在創建一個匿名數組。

創建一個匿名數組是很容易的:

$array = [ 'Bill', 'Ben, 'Mary' ];

這一行分配一個數組,由封閉的方括號中,而不是正常的括號表示,標量$array。賦值的右側上的值,使該陣列和左側包含此陣列的參考。

您可以創建更複雜的結構,通過嵌套數組:

@arrayarray = ( 1, 2, [1, 2, 3]);

@array數組包含三個元素,一個匿名的三個元素的數組的第三個元素是一個引用。

匿名散列

匿名哈希,你也很容易創建需要使用大括號方括號:

$hash = { 'Man' => 'Bill',
          'Woman' => 'Mary,
          'Dog' => 'Ben'
};

解除引用

解引用一個參考的最直接的方法是在前麵加上相應的數據類型的字符(標量使用$,陣列使用@,哈希使用,子程序用&)是你期待在前麵的標量量變量包含的引用。

$array = \@ARGV;     # Create reference to array
$hash = \%ENV;       # Create reference to hash
$glob = \*STDOUT;    # Create reference to typeglob
$foosub = \&foo;     # Create reference to subroutine
#by www.gitbook.net
push (@$array, "From humans");
$$array[0] = 'Hello'
$$hash{'Hello'} = 'World';
&$foosub;
print $glob "Hello World!\n";

對象基礎

主要有三種,解釋的Perl如何處理對象的角度來看。 該使用條款是對象,類和方法。

  • 在Perl中,對象僅僅是一個參考的數據類型,它知道它屬於什麼類。對象存儲在一個標量變量作為參考。因為一個標量隻包含一個對象的引用,同樣的標量可以容納不同的對象,不同的類中。

  • 在Perl中類是一個包,其中包含需要相應的方法來創建和操作對象。

  • 在Perl中一個子程序,程序包定義的方法。該方法的第一個參數是一個對象引用或包名稱,取決於該方法是否影響當前對象或類。

Perl提供了bless()函數,用於返回一個引用,並成為一個對象。

定義一個類

定義一個類很簡單。在Perl中類是對應於一個包。要創建一個類,我們先建立一個包。包是一個獨立的單元,用戶定義的變量和子程序,它可以被重新使用一遍又一遍。他們提供了一個單獨的命名空間內保持一個Perl程序,子程序和變量以免與其他包中的衝突。

要聲明一個類名為Person,我們做:

package Person;

包定義的範圍延伸到該文件的末尾,或直到遇到另一個package關鍵字。

創建和使用對象

要創建一個類的實例(對象),我們需要一個對象的構造函數。此構造函數是一個在包中定義的方法。大多數程序員來命名這種新對象的構造方法,但在Perl中,可以使用任何名稱。

在Perl中的對象,我們可以使用任何類型的Perl變量。大多數Perl程序員選擇使用數組或哈希表的引用。

讓我們來創建我們的構造函數使用一個Perl的哈希參考我們的Person類;

當創建一個對象,你需要提供一個構造函數。這是一個子程序,它返回一個對象引用在一個包內。blessing包的類創建的對象引用。例如:

package Person;
sub new
{
    my $class = shift;
    my $self = {
        _firstName => shift,
        _lastName  => shift,
        _ssn       => shift,
    };
    # Print all the values just for clarification. 
    #by www.gitbook.net
    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;
}

每類方法通過類名作為第一個參數。 因此,在上麵的例子中的類名是“Person”。你可以試試這個打印$class的值。下一步將剩下的參數傳遞的方法。

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

讓我們看看到完整的例子:保持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};
}
#by www.gitbook.net
sub getFirstName {
    my( $self ) = @_;
    return $self->{_firstName};
}
1;

現在,在mail.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";

This will produce following result
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。 這被稱為“是一個”的關係,因為雇員是一個人。Perl有一個特殊的變量@ISA來鋪助,@ISA 管理(方法)繼承。

以下是使用繼承說明

  • Perl搜索指定對象的指定對象的類。

  • Perl搜索類中定義的對象類的@ISA陣列。

  • 如果冇有在步驟1和2找到方法,那麼如果找到一個在@ ISA樹,Perl使用AUTOLOAD子程序,

  • 如果仍然無法找到匹配的方法,那麼Perl搜索的方法在通用類(包),標準的Perl庫的一部分。

  • 如果方法還冇有被發現,那麼Perl放棄,並提出了一個運行時異常。

因此,要創建一個新的Employee類將繼承我們的Person類的方法和屬性,我們簡單的代碼:保持將此程式碼放入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.- by www.gitbook.net
$object->setFirstName( "Mohd." );

# Now get first name set by helper function.
$firstName = $object->getFirstName();
print "After Setting First Name is : $firstName\n";

This will produce following result
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和執行它

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


This will produce following result
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);
   }
}

析構函數和垃圾收集

如果你已經編程使用對象之前,而你將意識到需要創建一個析構函數。當你使用完要釋放分配的內存對象。Perl自動為您儘快的對象超出作用域。

如果你想實現你的析構函數關閉文件,或做一些額外的處理,那麼你需要定義一個特殊的方法,命名為destroy。 此方法會被調用的對象隻是在Perl之前釋放分配給它的內存。 在其他方麵,就像其他DESTROY方法,可以操作任何你喜歡對象,以便正確地關閉它。

析構函數的方法是簡單地一個成員函數(子程序)命名的破壞都會被自動調用

  • 當對象的引用變量超出了作用域。
  • 當對象引用的變量是未定義
  • 當腳本結束
  • 當Perl解釋器終止

有關實例:

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

另一種麵向對象實例

這裡是另一個很好的例子,這將有助於你了解麵向對象的概念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
#by www.gitbook.net

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