http://blog.chinaunix.net/uid-27464093-id-3308003.html
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.yiibai.com 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.yiibai.com 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.yiibai.com 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.yiibai.com $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.yiibai.com 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