PERLOOP

一、Perl 的 OOP 概念基础

Perl 并没有内建 class 语法(5.x),它是通过「包(package)+ bless + 方法调用」来模拟对象系统的。

1.1 对象是什么?

在 Perl 中,对象就是一个引用,通常是对哈希的引用,被 bless 成某个包的对象:

my $obj = bless {}, 'MyClass';

这表示:$obj 是一个哈希引用,它被标记为 MyClass 包的对象。

1.2 方法调用

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

三、继承(Inheritance)

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');

四、类方法、静态方法、类数据

4.1 类方法

就是使用类名调用方法,如:

Animal->new(name => "Foo");

此时 Perl 自动将类名当作第一个参数传入方法(如 new),你可以用 $class 来接收。

4.2 静态方法(类不变性)

Perl 没有 Java 那种强制静态函数的语法,但你可以自己写子程序,不依赖对象:

sub get_species {
    return "Canis lupus familiaris";
}

Dog::get_species() 调用即可。


五、访问控制:私有 vs 公有

Perl 没有真正意义上的私有变量,靠约定俗成或作用域封装。

约定:用 _ 开头表示私有方法或属性。

更严谨方式是用闭包:

package Secret;
use strict;
use warnings;

my $secret_data = {};  # 外部无法访问

sub reveal {
    return $secret_data;
}
1;

六、多态(Polymorphism)与 SUPER

子类覆盖父类方法即为多态。要调用父类版本,可使用:

$self->SUPER::method(@args);

例:

sub speak {
    my ($self) = @_;
    $self->SUPER::speak();  # 调用 Animal::speak
    print $self->{name} . " additionally barks!\n";
}

七、DESTROY 析构函数

对象销毁时自动调用:

sub DESTROY {
    my ($self) = @_;
    print $self->{name} . " is being destroyed.\n";
}

八、现代 Perl 的 OOP(推荐了解)

传统写法过于繁琐,现代 Perl 可以使用模块如:

例子(使用 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 写法类比语言
packageclass
构造函数sub new + blessconstructor
成员变量哈希字段 $self->{xxx}this.xxx
继承use parent / @ISAextends
方法调用$obj->method()obj.method()
多态与父类调用SUPER::method()super.method()

PERLPM

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


system() 函数示例

#!/usr/bin/perl

$PATH = "我是 Perl 的变量";

system('echo $PATH');      # shell 环境变量
system("echo $PATH");      # Perl 变量
system("echo \$PATH");     # 转义后的 shell 变量

1;

fork() + exec 示例

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

设置 SIG{CHLD} 为 IGNORE 示例

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

kill 函数示例

#!/usr/bin/perl

kill('INT', 104, 102);

1;

TCL

Tcl(Tool Command Language)是一种解释型脚本语言,广泛用于嵌入式系统、自动化测试等领域。tclsh hello.tcl

1. Hello World

puts "Hello, World!"

puts 用于打印字符串到标准输出。


2. 变量

set name "Tcl"
puts "Language: $name"

3. 条件语句

set score 85

if {$score >= 90} {
    puts "优秀"
} elseif {$score >= 60} {
    puts "及格"
} else {
    puts "不及格"
}

注意:


4. 循环

while 循环

set i 0
while {$i < 5} {
    puts "i = $i"
    incr i
}

for 循环

for {set i 0} {$i < 5} {incr i} {
    puts "for i = $i"
}

foreach 循环

set list {apple banana cherry}
foreach item $list {
    puts "Fruit: $item"
}

5. 数组

array set fruits {
    apple 3
    banana 5
    cherry 7
}

puts "Apple count: $fruits(apple)"

# 遍历数组
foreach key [array names fruits] {
    puts "$key => $fruits($key)"
}