面向对象编程 #

一、Perl OOP概述 #

Perl的面向对象基于三个核心概念:

  • :一个包(package)
  • 对象:一个被bless的引用
  • 方法:第一个参数为对象或类的子程序

二、创建类 #

2.1 基本类结构 #

perl
package Person;
use strict;
use warnings;

sub new {
    my $class = shift;
    my $self = {
        name => shift,
        age  => shift,
    };
    bless $self, $class;
    return $self;
}

sub name {
    my $self = shift;
    return $self->{name};
}

sub age {
    my $self = shift;
    return $self->{age};
}

1;

2.2 使用类 #

perl
use Person;

my $person = Person->new("Tom", 25);
print $person->name();
print $person->age();

2.3 bless函数 #

bless 将引用与包关联:

perl
my $hash_ref = { name => "Tom" };
bless $hash_ref, "Person";

三、构造函数 #

3.1 标准构造函数 #

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

3.2 带参数的构造函数 #

perl
sub new {
    my $class = shift;
    my %args = @_;
    
    my $self = {
        name => $args{name} // "Unknown",
        age  => $args{age}  // 0,
    };
    
    bless $self, $class;
    return $self;
}

使用:

perl
my $person = Person->new(
    name => "Tom",
    age  => 25,
);

3.3 初始化方法 #

perl
sub new {
    my $class = shift;
    my $self = bless {}, $class;
    $self->_init(@_);
    return $self;
}

sub _init {
    my ($self, %args) = @_;
    $self->{name} = $args{name} // "Unknown";
    $self->{age}  = $args{age}  // 0;
}

四、方法 #

4.1 实例方法 #

perl
sub greet {
    my $self = shift;
    print "Hello, I'm " . $self->{name} . "\n";
}

$person->greet();

4.2 访问器 #

perl
sub name {
    my $self = shift;
    if (@_) {
        $self->{name} = shift;
    }
    return $self->{name};
}

sub age {
    my $self = shift;
    if (@_) {
        $self->{age} = shift;
    }
    return $self->{age};
}

使用:

perl
print $person->name();
$person->name("Jerry");
print $person->name();

4.3 类方法 #

perl
our $count = 0;

sub new {
    my $class = shift;
    $count++;
    my $self = bless {}, $class;
    return $self;
}

sub get_count {
    my $class = shift;
    return $count;
}

print Person->get_count();

五、继承 #

5.1 使用@ISA #

perl
package Employee;
use strict;
use warnings;
use parent 'Person';

sub new {
    my $class = shift;
    my $self = $class->SUPER::new(@_);
    $self->{salary} = shift // 0;
    return $self;
}

sub salary {
    my $self = shift;
    return $self->{salary};
}

1;

5.2 使用parent模块 #

perl
package Employee;
use parent 'Person';

sub new {
    my $class = shift;
    my $self = $class->SUPER::new(@_);
    $self->{salary} = shift // 0;
    return $self;
}

5.3 调用父类方法 #

perl
sub greet {
    my $self = shift;
    $self->SUPER::greet();
    print "I earn " . $self->{salary} . "\n";
}

5.4 多重继承 #

perl
package Manager;
use parent qw(Employee Administrator);

六、完整示例 #

6.1 Person类 #

perl
package Person;
use strict;
use warnings;

sub new {
    my $class = shift;
    my %args = @_;
    
    my $self = {
        name => $args{name} // "Unknown",
        age  => $args{age}  // 0,
    };
    
    bless $self, $class;
    return $self;
}

sub name {
    my $self = shift;
    $self->{name} = shift if @_;
    return $self->{name};
}

sub age {
    my $self = shift;
    $self->{age} = shift if @_;
    return $self->{age};
}

sub greet {
    my $self = shift;
    print "Hello, I'm " . $self->name . ", " . $self->age . " years old.\n";
}

sub to_string {
    my $self = shift;
    return sprintf("Person{name=%s, age=%d}", $self->name, $self->age);
}

1;

6.2 Employee类 #

perl
package Employee;
use strict;
use warnings;
use parent 'Person';

sub new {
    my $class = shift;
    my %args = @_;
    
    my $self = $class->SUPER::new(
        name => $args{name},
        age  => $args{age},
    );
    
    $self->{salary} = $args{salary} // 0;
    $self->{department} = $args{department} // "Unknown";
    
    return $self;
}

sub salary {
    my $self = shift;
    $self->{salary} = shift if @_;
    return $self->{salary};
}

sub department {
    my $self = shift;
    $self->{department} = shift if @_;
    return $self->{department};
}

sub greet {
    my $self = shift;
    print "Hello, I'm " . $self->name . ", working in " . $self->department . "\n";
}

sub to_string {
    my $self = shift;
    return sprintf("Employee{name=%s, age=%d, salary=%d, dept=%s}",
        $self->name, $self->age, $self->salary, $self->department);
}

1;

6.3 使用示例 #

perl
#!/usr/bin/perl
use strict;
use warnings;
use v5.10;

use Person;
use Employee;

my $person = Person->new(name => "Tom", age => 25);
$person->greet();
say $person->to_string();

my $employee = Employee->new(
    name       => "Jerry",
    age        => 30,
    salary     => 50000,
    department => "Engineering",
);
$employee->greet();
say $employee->to_string();

七、Moose模块 #

现代Perl推荐使用 Moose 进行面向对象编程:

perl
package Person;
use Moose;

has name => (is => 'rw', isa => 'Str');
has age  => (is => 'rw', isa => 'Int');

sub greet {
    my $self = shift;
    print "Hello, I'm " . $self->name . "\n";
}

no Moose;
1;

使用:

perl
use Person;

my $person = Person->new(name => "Tom", age => 25);
$person->greet();
$person->age(26);

八、实践练习 #

练习1:银行账户类 #

perl
package BankAccount;
use strict;
use warnings;

sub new {
    my $class = shift;
    my %args = @_;
    
    my $self = {
        balance => $args{balance} // 0,
    };
    
    bless $self, $class;
    return $self;
}

sub balance {
    my $self = shift;
    return $self->{balance};
}

sub deposit {
    my ($self, $amount) = @_;
    $self->{balance} += $amount;
    return $self->{balance};
}

sub withdraw {
    my ($self, $amount) = @_;
    if ($amount > $self->{balance}) {
        die "Insufficient funds\n";
    }
    $self->{balance} -= $amount;
    return $self->{balance};
}

1;

练习2:购物车类 #

perl
package ShoppingCart;
use strict;
use warnings;

sub new {
    my $class = shift;
    my $self = {
        items => [],
    };
    bless $self, $class;
    return $self;
}

sub add_item {
    my ($self, $name, $price, $quantity) = @_;
    $quantity //= 1;
    push @{$self->{items}}, {
        name     => $name,
        price    => $price,
        quantity => $quantity,
    };
}

sub total {
    my $self = shift;
    my $total = 0;
    $total += $_->{price} * $_->{quantity} foreach @{$self->{items}};
    return $total;
}

sub items {
    my $self = shift;
    return @{$self->{items}};
}

1;

九、总结 #

本章学习了:

  • Perl OOP的基本概念
  • 使用bless创建对象
  • 构造函数和方法
  • 继承和多态
  • Moose模块简介

下一章将学习高级主题。

最后更新:2026-03-27