Perl berorientasikan objek


Terdapat dua pelaksanaan berbeza pengaturcaraan berorientasikan objek dalam Perl:

  • Satu adalah berdasarkan jadual cincang tanpa nama Inti bagi setiap contoh objek ialah rujukan penunjuk A ke jadual cincang tanpa nama. Dalam jadual cincang tanpa nama ini, semua atribut contoh disimpan.

  • Yang kedua adalah berdasarkan tatasusunan, kami akan mencipta tatasusunan untuk setiap atribut contoh, dan intipati setiap contoh objek ialah penunjuk kepada tatasusunan ini kepada indeks baris. Dalam tatasusunan ini, semua sifat contoh disimpan.


Konsep asas berorientasikan objek

Terdapat banyak konsep asas berorientasikan objek, di sini kita menerima tiga: objek, kelas dan kaedah.

  • Objek : Objek ialah rujukan kepada item data dalam kelas. .

  • Kelas: Kelas ialah pakej Perl yang mengandungi kelas yang menyediakan kaedah objek.

  • Kaedah: Kaedah ini ialah subrutin Perl dan nama kelas ialah parameter pertamanya.

Perl menyediakan fungsi bless() yang digunakan untuk membina objek.


Takrifan kelas

Kelas hanyalah pakej ringkas.

Anda boleh menggunakan pakej sebagai kelas, dan menggunakan fungsi dalam pakej sebagai kaedah kelas.

Pakej Perl menyediakan ruang nama bebas, jadi kaedah dan nama pembolehubah dalam pakej berbeza tidak akan bercanggah.

Pelanjutan fail kelas Perl ialah .pm.

Seterusnya kami mencipta kelas Orang:

package Person;

Julat kod kelas mencapai baris terakhir fail skrip, atau sebelum kata kunci pakej seterusnya.


Mencipta dan menggunakan objek

Untuk mencipta contoh (objek) kelas kita perlu mentakrifkan pembina, kebanyakan program menggunakan nama kelas sebagai pembina, sebarang nama boleh digunakan dalam Perl.

Anda boleh menggunakan pelbagai pembolehubah Perl sebagai objek Perl. Selalunya kami akan menggunakan tatasusunan rujukan atau cincang.

Seterusnya kami mencipta pembina untuk kelas Person, menggunakan rujukan cincangan Perl.

Apabila mencipta objek, anda perlu menyediakan pembina, iaitu subrutin yang mengembalikan rujukan kepada objek.

Contohnya adalah seperti berikut:

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

Seterusnya kita cipta objek:

$object = new Person( "小明", "王", 23234345);

Tentukan kaedah

Kaedah kelas Perl hanyalah anak Perl Ia hanya satu program, juga dikenali sebagai fungsi ahli.

Takrif kaedah Perl dalam Perl berorientasikan objek tidak menyediakan sebarang sintaks khas, tetapi menetapkan bahawa parameter pertama kaedah ialah objek atau pakej yang dirujuk.

Perl tidak menyediakan pembolehubah peribadi, tetapi kami boleh mengurus data objek melalui kaedah tambahan.

Seterusnya kita tentukan kaedah untuk mendapatkan nama:

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

Ia juga boleh ditulis seperti ini:

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

Seterusnya kita ubah suai kod fail Person.pm, seperti yang ditunjukkan di bawah:

#!/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 Kod skrip adalah seperti berikut:

#!/usr/bin/perl

use Person;

$object = new Person( "小明", "王", 23234345);
# 获取姓名
$firstName = $object->getFirstName();

print "设置前姓名为 : $firstName\n";

# 使用辅助函数设置姓名
$object->setFirstName( "小强" );

# 通过辅助函数获取姓名
$firstName = $object->getFirstName();
print "设置后姓名为 : $firstName\n";

Selepas melaksanakan program di atas, hasil output ialah:

$ perl employee.pl
名字:小明
姓氏:王
编号:23234345
设置前姓名为 : 小明
设置后姓名为 : 小强

Warisi

Dalam Perl, kaedah kelas diwarisi melalui tatasusunan @ISA ini mengandungi nama pakej lain (kelas) Warisan pembolehubah mesti ditetapkan secara eksplisit.

Warisan berbilang bermakna tatasusunan @ISA mengandungi berbilang nama kelas (pakej).

Hanya kaedah boleh diwarisi melalui @ISA, bukan data.

Seterusnya kami mencipta kelas Pekerja yang mewarisi kelas Orang.

Kod fail Employee.pm adalah seperti berikut:

#!/usr/bin/perl

package Employee;
use Person;
use strict;
our @ISA = qw(Person);    # 从 Person 继承

Kini kelas Pekerja mengandungi semua kaedah dan sifat kelas Person Kami masukkan kod berikut dalam main.pl fail dan laksanakannya:

#!/usr/bin/perl

use Employee;

$object = new Employee( "小明", "王", 23234345);
# 获取姓名
$firstName = $object->getFirstName();

print "设置前姓名为 : $firstName\n";

# 使用辅助函数设置姓名
$object->setFirstName( "小强" );

# 通过辅助函数获取姓名
$firstName = $object->getFirstName();
print "设置后姓名为 : $firstName\n";

Selepas melaksanakan atur cara di atas, hasil output ialah:

$ perl main.pl
名字:小明
姓氏:王
编号:23234345
设置前姓名为 : 小明
设置后姓名为 : 小强

Kaedah penulisan semula

Dalam contoh di atas, kelas Pekerja mewarisi kelas Orang, tetapi jika kelas Orang Jika kaedah tidak dapat memenuhi keperluan, kaedah itu perlu ditulis semula.

Seterusnya kami menambah beberapa kaedah baharu pada kelas Pekerja dan mengatasi kaedah kelas Orang:

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

Kami memasukkan kod berikut dalam fail main.pl dan laksanakan:

#!/usr/bin/perl

use Employee;

$object = new Employee( "小明", "王", 23234345);
# 获取姓名,使用修改后的构造函数
$firstName = $object->getFirstName();

print "设置前姓名为 : $firstName\n";

# 使用辅助函数设置姓名
$object->setFirstName( "小强" );

# 通过辅助函数获取姓名
$firstName = $object->getFirstName();
print "设置后姓名为 : $firstName\n";

Selepas melaksanakan program di atas, hasil output ialah:

$ perl main.pl
名字:小明
姓氏:王
编号:23234345
这是子类函数
设置前姓名为 : 小明
这是子类函数
设置后姓名为 : 小强

Dimuatkan secara lalai

Jika ia berada dalam kelas semasa, semua kelas asas kelas semasa, dan kelas UNIVERSAL saya tidak dapat mencari cara untuk memintanya. Pada masa ini, kaedah bernama AUTOLOAD() dicari sekali lagi. Jika AUTOLOAD ditemui, maka Panggil dan tetapkan pembolehubah global $AUTOLOAD kepada nama yang layak sepenuhnya bagi kaedah yang tiada.

Jika itu tidak berjaya, Perl gagal dengan ralat.

Jika anda tidak mahu mewarisi AUTOLOAD kelas asas, ia sangat mudah, hanya satu ayat:

sub AUTOLOAD;

Pemusnah dan pengumpulan sampah

Apabila rujukan terakhir objek Apabila dilepaskan, objek secara automatik dimusnahkan.

Jika anda ingin melakukan sesuatu semasa pemusnahan, maka anda boleh menentukan kaedah bernama "DESTROY" dalam kelas. Ia akan dipanggil secara automatik pada masa yang sesuai dan melakukan tindakan pembersihan tambahan seperti yang anda mahu.

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

Perl menganggap rujukan objek sebagai Satu-satunya hujah yang diluluskan ialah HANCURKAN. Ambil perhatian bahawa rujukan ini adalah baca sahaja, yang bermaksud anda tidak boleh mengubah suainya dengan mengakses $_[0]. (Nota Penterjemah: Lihat perlsub) Tetapi objek itu sendiri (seperti "${$_[0]" Atau "@{$_[0]}" dan "%{$_[0]}" dsb.) masih boleh ditulis.

Jika anda memberkati semula rujukan objek sebelum pemusnah kembali, Perl kemudian akan memanggil kaedah DESTROY bagi objek yang anda berkati semula selepas pemusnah kembali. Ini memberi anda peluang untuk memanggil pemusnah kelas asas atau kelas lain yang anda tentukan. Perlu diingatkan bahawa DESTROY juga boleh dipanggil secara manual, tetapi biasanya tidak perlu melakukannya.

Selepas objek semasa dilepaskan, objek lain yang terkandung dalam objek semasa akan dikeluarkan secara automatik.


Contoh berorientasikan objek Perl

Kita boleh memahami lebih lanjut aplikasi berorientasikan objek Perl melalui contoh berikut:

#!/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";
# 自动执行析构函数

Laksanakan program di atas, output hasilnya ialah:

调用 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