Perl 并没有内建 class 语法(5.x),它是通过「包(package)+ bless + 方法调用」来模拟对象系统的。
在 Perl 中,对象就是一个引用,通常是对哈希的引用,被 bless 成某个包的对象:
my $obj = bless {}, 'MyClass';
这表示:$obj 是一个哈希引用,它被标记为 MyClass 包的对象。
Perl 的方法调用用 -> 操作符实现:
$obj->method(@args);
此调用会把 $obj 作为第一个参数传入 MyClass::method 子程序中。
我们来手动写一个完整的类 Animal,支持构造对象和访问属性。
# Animal.pm
package Animal;
use strict;
use warnings;
# 构造器
sub new {
my ($class, %args) = @_;
my $self = {
name => $args{name} || 'Unnamed',
age => $args{age} || 0,
};
bless $self, $class;
return $self;
}
# 方法
sub speak {
my ($self) = @_;
print $self->{name} . " makes a noise.\n";
}
sub get_name {
my ($self) = @_;
return $self->{name};
}
sub set_name {
my ($self, $name) = @_;
$self->{name} = $name;
}
1;
使用方式:
# main.pl
use strict;
use warnings;
use Animal;
my $a = Animal->new(name => "Dog", age => 5);
$a->speak; # Dog makes a noise.
print $a->get_name . "\n"; # Dog
Perl 的继承通过 @ISA 数组声明父类。
# Dog.pm
package Dog;
use strict;
use warnings;
use parent 'Animal'; # 自动设置 @ISA
sub speak {
my ($self) = @_;
print $self->{name} . " barks!\n";
}
1;
测试:
use Dog;
my $d = Dog->new(name => "Buddy", age => 3);
$d->speak; # Buddy barks!
如果不想用 parent 模块,也可以手动设置:
our @ISA = ('Animal');
就是使用类名调用方法,如:
Animal->new(name => "Foo");
此时 Perl 自动将类名当作第一个参数传入方法(如 new),你可以用 $class 来接收。
Perl 没有 Java 那种强制静态函数的语法,但你可以自己写子程序,不依赖对象:
sub get_species {
return "Canis lupus familiaris";
}
用 Dog::get_species() 调用即可。
Perl 没有真正意义上的私有变量,靠约定俗成或作用域封装。
约定:用 _ 开头表示私有方法或属性。
更严谨方式是用闭包:
package Secret;
use strict;
use warnings;
my $secret_data = {}; # 外部无法访问
sub reveal {
return $secret_data;
}
1;
子类覆盖父类方法即为多态。要调用父类版本,可使用:
$self->SUPER::method(@args);
例:
sub speak {
my ($self) = @_;
$self->SUPER::speak(); # 调用 Animal::speak
print $self->{name} . " additionally barks!\n";
}
对象销毁时自动调用:
sub DESTROY {
my ($self) = @_;
print $self->{name} . " is being destroyed.\n";
}
传统写法过于繁琐,现代 Perl 可以使用模块如:
Moose:功能强大,支持类型、角色、继承等
[Moo]:轻量版的 Moose
[Object::Tiny, Class::Tiny]:极简
例子(使用 Moo):
package Animal;
use Moo;
has name => (is => 'rw');
has age => (is => 'rw');
sub speak {
my $self = shift;
print $self->name . " makes a noise.\n";
}
| 概念 | Perl 写法 | 类比语言 |
|---|---|---|
| 类 | package | class |
| 构造函数 | sub new + bless | constructor |
| 成员变量 | 哈希字段 $self->{xxx} | this.xxx |
| 继承 | use parent / @ISA | extends |
| 方法调用 | $obj->method() | obj.method() |
| 多态与父类调用 | SUPER::method() | super.method() |
Perl 中你可以以不同的方法来创建进程。 本教程将讨论一些进程的管理方法。
$$ 或 $PROCESS_ID 来获取进程 ID。%ENV 哈希存放了父进程,也就是shell中的环境变量,在Perl中可以修改这些变量。#!/usr/bin/perl
@files = `ls -l`;
foreach $file (@files){
print $file;
}
1;
执行以上程序,输出结果如下:
drwxr-xr-x 3 root root 4096 Sep 14 06:46 9-14 drwxr-xr-x 4 root root 4096 Sep 13 07:54 android -rw-r–r– 1 root root 574 Sep 17 15:16 index.htm drwxr-xr-x 3 544 401 4096 Jul 6 16:49 MIME-Lite-3.01 -rw-r–r– 1 root root 71 Sep 17 15:16 test.pl
#!/usr/bin/perl
$PATH = "我是 Perl 的变量";
system('echo $PATH'); # shell 环境变量
system("echo $PATH"); # Perl 变量
system("echo \$PATH"); # 转义后的 shell 变量
1;
#!/usr/bin/perl
if(!defined($pid = fork())) {
die "无法创建子进程: $!";
} elsif ($pid == 0) {
print "通过子进程输出\n";
exec("date") || die "无法输出日期: $!";
} else {
print "通过父进程输出\n";
$ret = waitpid($pid, 0);
print "完成的进程ID: $ret\n";
}
1;
#!/usr/bin/perl
local $SIG{CHLD} = "IGNORE";
if(!defined($pid = fork())) {
die "无法创建子进程: $!";
} elsif ($pid == 0) {
print "通过子进程输出\n";
exec("date") || die "无法输出日期: $!";
} else {
print "通过父进程输出\n";
$ret = waitpid($pid, 0);
print "完成的进程ID: $ret\n";
}
1;
#!/usr/bin/perl
kill('INT', 104, 102);
1;
Tcl(Tool Command Language)是一种解释型脚本语言,广泛用于嵌入式系统、自动化测试等领域。tclsh hello.tcl
puts "Hello, World!"
puts 用于打印字符串到标准输出。
set name "Tcl"
puts "Language: $name"
set 用于赋值
$name 表示取变量值
set score 85
if {$score >= 90} {
puts "优秀"
} elseif {$score >= 60} {
puts "及格"
} else {
puts "不及格"
}
注意:
条件和花括号之间 要有空格
逻辑表达式必须用 {} 包起来
set i 0
while {$i < 5} {
puts "i = $i"
incr i
}
for {set i 0} {$i < 5} {incr i} {
puts "for i = $i"
}
set list {apple banana cherry}
foreach item $list {
puts "Fruit: $item"
}
array set fruits {
apple 3
banana 5
cherry 7
}
puts "Apple count: $fruits(apple)"
# 遍历数组
foreach key [array names fruits] {
puts "$key => $fruits($key)"
}