英语法语西班牙文

OnWorks 网站图标

perltie - 云端在线

通过 Ubuntu Online、Fedora Online、Windows 在线模拟器或 MAC OS 在线模拟器在 OnWorks 免费托管服务提供商中运行 perltie

这是可以使用我们的多个免费在线工作站之一在 OnWorks 免费托管服务提供商中运行的命令 perltie,例如 Ubuntu Online、Fedora Online、Windows 在线模拟器或 MAC OS 在线模拟器

程序:

您的姓名


perltie - 如何在简单变量中隐藏对象类

概要


领带变量,类名,列表

$object = 绑定变量

解开变量

商品描述


在 Perl 5.0 发布之前,程序员可以使用 数据库打开() 连接磁盘
标准 Unix 中的数据库 数据库(3x) 在他们的程序中神奇地格式化为 %HASH。
然而,他们的 Perl 要么是用一个特定的 dbm 库构建的,要么是用另一个库构建的,但不是
两者,并且您不能将此机制扩展到其他包或变量类型。

现在你可以。

这款 领带() 函数将一个变量绑定到一个类(包),该类将提供
该变量的访问方法的实现。 一旦施展了这个魔法,
访问绑定变量会自动触发正确类中的方法调用。 这
类的复杂性隐藏在魔术方法调用之后。 方法名称在所有
CAPS,这是 Perl 用来指示它们被隐式调用的约定
而不是明确的——就像 开始()结尾() 功能。

领带() 调用,“VARIABLE”是要附魔的变量的名称。 “类名”是
实现正确类型对象的类的名称。 中的任何附加参数
“LIST”被传递给该类的适当构造方法——意思是
关系标量(), 蒂亚雷(), 领带()领带(). (通常这些是这样的论点
可能会传递给 数据库初始化() C.) 由“new”返回的对象
方法也由 领带() 功能,如果您想,这将很有用
访问“CLASSNAME”中的其他方法。 (您实际上不必返回对 a 的引用
正确的“类型”(例如,HASH 或“CLASSNAME”),只要它是一个适当的祝福对象。)你
还可以使用 绑() 功能。

不比 数据库打开()领带() 函数不会为你“使用”或“需要”一个模块——你
需要自己明确地做到这一点。

搭售 标量
实现绑定标量的类应定义以下方法:TIESCALAR、FETCH、
存储,并可能解开和/或销毁。

让我们依次查看每一个,以标量的关系类为例,它允许
用户执行以下操作:

领带 $his_speed, 'Nice', getppid();
领带 $my_speed, 'Nice', $$;

现在每当访问这些变量中的任何一个时,其当前的系统优先级是
取回并返回。 如果设置了这些变量,那么进程的优先级是
变了!

我们将使用 Jarkko Hietaniemi[电子邮件保护]> 的 BSD::Resource 类(未包含)访问
系统中的 PRIO_PROCESS、PRIO_MIN 和 PRIO_MAX 常量,以及
获取优先级()设置优先级() 系统调用。 这是课程的序言。

包不错;
使用鲤鱼;
使用 BSD::Resource;
用严格;
$Nice::DEBUG = 0 除非定义 $Nice::DEBUG;

TIESCALAR 类名,列表
这是类的构造函数。 这意味着它有望返回一个有福的
对它正在创建的新标量(可能是匿名的)的引用。 例如:

子 TIESCALAR {
我的 $class = shift;
我的 $pid = shift || $$; # 0 表示我

如果 ($pid !~ /^\d+$/) {
carp "Nice::Tie::Scalar got non-numeric pid $pid" if $^W;
返回 undef;
}

除非 (kill 0, $pid) { # EPERM 或 ERSCH,毫无疑问
carp "Nice::Tie::Scalar 得到了错误的 pid $pid: $!" 如果 $^W;
返回 undef;
}

返回祝福 \$pid, $class;
}

这个关系类选择返回错误而不是引发异常,如果它
构造函数应该失败。 虽然这是如何 数据库打开() 有效,其他类可能很好
不想那么宽容。 它检查全局变量 $^W 以查看是否发出
反正有点噪音。

取这个
每次访问(读取)绑定变量时都会触发此方法。 它
除了它的自引用之外不接受任何参数,自引用是表示
我们正在处理的标量。 因为在这种情况下,我们只使用 SCALAR ref 作为
绑定标量对象,一个简单的 $$self 允许该方法获取存储的实际值
那里。 在下面的示例中,实际值是我们绑定的进程 ID
我们的变量。

子取回{
我的 $self = shift;
承认“错误类型”,除非 ref $self;
如果@_,则发出“使用错误”的声音;
我的 $nicety;
本地($!)= 0;
$nicety = getpriority(PRIO_PROCESS, $$self);
if ($!) { croak "getpriority failed: $!" }
返回 $nicety;
}

这次我们决定在 renice 失败时炸毁(提出一个例外)——有
否则我们没有地方返回错误,这可能是正确的做法。

存储这个,价值
每次设置(分配)绑定变量时都会触发此方法。 超过
它的自引用,它还需要一个(并且只有一个)参数:新值
用户正在尝试分配。 不要担心从 STORE 返回一个值; 语义
返回赋值的赋值是用 FETCH 实现的。

子商店{
我的 $self = shift;
承认“错误类型”,除非 ref $self;
我的 $new_nicety = shift;
如果@_,则发出“使用错误”的声音;

如果($new_nicety < PRIO_MIN){
鲤鱼
“警告:优先级 %d 小于最小系统优先级 %d”,
$new_nicety, PRIO_MIN 如果 $^W;
$new_nicety = PRIO_MIN;
}

如果($new_nicety > PRIO_MAX){
鲤鱼
“警告:优先级 %d 大于最大系统优先级 %d”,
$new_nicety, PRIO_MAX 如果 $^W;
$new_nicety = PRIO_MAX;
}

除非(定义 setpriority(PRIO_PROCESS,$$self,$new_nicety)){
承认“setpriority 失败:$!”;
}
}

解开这个
当“解开”发生时将触发此方法。 如果类
需要知道什么时候不再进行调用。 (当然,DESTROY 除外。)参见“The
“解开“陷阱”以了解更多详情。

摧毁这个
当绑定变量需要销毁时,会触发该方法。 与
其他对象类,很少需要这样的方法,因为 Perl 释放了它的
自动为您保存垂死的对象内存——这不是 C++,你知道。 我们将使用一个
此处的 DESTROY 方法仅用于调试目的。

子销毁{
我的 $self = shift;
承认“错误类型”,除非 ref $self;
carp "[ Nice::DESTROY pid $$self ]" if $Nice::DEBUG;
}

这就是它的全部内容。 实际上,这比一切都重要,因为
为了完整性、健壮性和通用性,我们在这里做了一些不错的事情
美学。 更简单的 TIESCALAR 类当然是可能的。

搭售 阵列
实现绑定普通数组的类应该定义以下方法:TIEARRAY、
FETCH、STORE、FETCHSIZE、STORESIZE、CLEAR 和 UNTIE 和/或 DESTROY。

FETCHSIZE 和 STORESIZE 用于提供 $#array 和等效的“scalar(@array)”
访问。

如果 perl 需要使用 POP、PUSH、SHIFT、UNSHIFT、SPLICE、DELETE 和 EXISTS 方法
具有相应(但小写)名称的运算符用于对绑定数组进行操作。 这
领带::数组 类可以用作基类来实现前五个方面
上面的基本方法。 DELETE 和 EXISTS 的默认实现
领带::数组 简直就是“呲牙咧嘴”。

此外,当 perl 将在实际中预先扩展分配时,将调用 EXTEND
数组。

在本次讨论中,我们将实现一个数组,其元素在创建时具有固定大小。
如果您尝试创建大于固定大小的元素,则会出现异常。 为了
例:

使用 FixedElem_Array;
领带@array, 'FixedElem_Array', 3;
$array[0] = '猫'; # 行。
$array[1] = '狗'; # 例外,长度('狗')> 3。

该类的序言代码如下:

包 FixedElem_Array;
使用鲤鱼;
用严格;

TIEARRAY 类名,列表
这是类的构造函数。 这意味着它有望返回一个有福的
新数组(可能是匿名数组引用)将通过该引用
访问。

在我们的示例中,只是为了向您表明您没有 必须返回一个数组
引用,我们将选择一个 HASH 引用来表示我们的对象。 一个哈希计算出来
以及通用记录类型:“{ELEMSIZE}”字段将存储最大元素
允许大小,“{ARRAY}”字段将保存真正的 ARRAY 引用。 如果有人
在类之外尝试取消引用返回的对象(毫无疑问认为它是
ARRAY ref),它们会爆炸。 这只是表明你应该尊重
对象的隐私。

子 TIEARRAY {
我的 $class = shift;
我的 $elemsize = shift;
if (@_ || $elemsize =~ /\D/) {
呱呱 "用法: 领带 ARRAY, '" . __包裹__ 。 "', elem_size";
}
返回祝福{
ELEMSIZE => $elemsize,
数组 => [],
},$类;
}

获取这个,索引
每次绑定数组的单个元素时都会触发此方法
访问(读取)。 它需要一个超出其自身引用的参数:索引
我们试图获取的值。

子取回{
我的 $self = shift;
我的 $index = shift;
返回 $self->{ARRAY}->[$index];
}

如果使用负数组索引从数组中读取,则索引将被转换
在传递给 FETCH 之前,通过调用 FETCHSIZE 在内部将其变为正数。 你
可以通过为变量 $NEGATIVE_INDICES 分配一个真值来禁用此功能
在绑定数组类中。

您可能已经注意到,FETCH 方法(等)的名称对于所有
访问,即使构造函数的名称不同(TIESCALAR 与 TIEARRAY)。 尽管
理论上,你可以让同一个类为多个绑定类型提供服务,实际上这个
变得很麻烦,而且最容易将它们保持在每个班级的一种领带类型。

存储这个,索引,值
每次设置绑定数组中的元素时都会触发此方法
(书面)。 除了它的自引用之外,它还有两个参数:我们所在的索引
试图存储一些东西以及我们试图放在那里的价值。

在我们的例子中,“undef”实际上是“$self->{ELEMSIZE}”的空格数,所以我们有一个
这里还有一些工作要做:

子商店{
我的 $self = shift;
我的( $index, $value ) = @_;
如果(长度 $value > $self->{ELEMSIZE} ){
croak "$value 的长度大于 $self->{ELEMSIZE}";
}
# 填空
$self->EXTEND( $index ) 如果 $index > $self->FETCHSIZE();
# 右对齐以保持较小元素的元素大小
$self->{ARRAY}->[$index] = sprintf "%$self->{ELEMSIZE}s", $value;
}

负索引的处理方式与 FETCH 相同。

FETCHSIZE 这个
返回与对象关联的绑定数组中的项目总数 Free Introduction.
(相当于“标量(@array)”)。 例如:

子 FETCHSIZE {
我的 $self = shift;
返回标量@{$self->{ARRAY}};
}

STORESIZE 这个,计数
设置与对象关联的绑定数组中的项目总数 Free Introduction 成为
. 如果这使数组变大,那么类的“undef”映射应该是
返回新职位。 如果数组变小,则条目超出计数
应该删除。

在我们的例子中,'undef' 实际上是一个包含 "$self->{ELEMSIZE}" 数量的元素
空间。 观察:

子商店大小{
我的 $self = shift;
我的 $count = shift;
如果 ( $count > $self->FETCHSIZE() ) {
foreach ( $count - $self->FETCHSIZE() .. $count ) {
$self->STORE( $_, '' );
}
} elsif ( $count < $self->FETCHSIZE() ) {
foreach ( 0 .. $self->FETCHSIZE() - $count - 2 ) {
$self->POP();
}
}
}

扩展这个,计数
该数组可能会增长的信息性调用 条目。 可用于
优化分配。 这个方法什么都不用做。

在我们的示例中,我们要确保没有空白(“undef”)条目,因此“EXTEND”
将根据需要使用“STORESIZE”来填充元素:

子扩展{
我的 $self = shift;
我的 $count = shift;
$self->STORESIZE( $count );
}

存在这个,关键
验证索引处的元素 存在于绑定数组中 Free Introduction.

在我们的示例中,我们将确定一个元素是否包含“$self->{ELEMSIZE}”
只有空格,它不存在:

子存在{
我的 $self = shift;
我的 $index = shift;
返回 0 如果! 定义 $self->{ARRAY}->[$index] ||
$self->{ARRAY}->[$index] eq ' ' x $self->{ELEMSIZE};
1返回;
}

删除这个,关键
删除索引处的元素 从绑定数组 Free Introduction.

在我们的示例中,删除的项目是“$self->{ELEMSIZE}”空格:

子删除{
我的 $self = shift;
我的 $index = shift;
返回 $self->STORE( $index, '' );
}

清除这个
清除(移除、删除、...)与对象关联的绑定数组中的所有值
Free Introduction。 例如:

子清除{
我的 $self = shift;
返回 $self->{ARRAY} = [];
}

推这个,列表
附加元素 清单 到数组。 例如:

子推{
我的 $self = shift;
我的@list = @_;
我的 $last = $self->FETCHSIZE();
$self->STORE( $last + $_, $list[$_] ) foreach 0 .. $#list;
返回 $self->FETCHSIZE();
}

弹出这个
删除数组的最后一个元素并返回它。 例如:

子 POP {
我的 $self = shift;
return pop @{$self->{ARRAY}};
}

移动这个
删除数组的第一个元素(向下移动其他元素)并返回它。
例如:

子移位{
我的 $self = shift;
return shift @{$self->{ARRAY}};
}

取消这个,列出
在数组的开头插入 LIST 元素,将现有元素向上移动到
腾地方。 例如:

子 UNSHIFT {
我的 $self = shift;
我的@list = @_;
我的 $size = 标量(@list);
# 为我们的列表腾出空间
@{$self->{ARRAY}}[ $size .. $#{$self->{ARRAY}} + $size ]
= @{$self->{ARRAY}};
$self->STORE( $_, $list[$_] ) foreach 0 .. $#list;
}

SPLICE this,偏移量,长度,LIST
在阵列上执行相当于“拼接”的操作。

抵消 是可选的,默认为零,负值从末尾开始计数
数组。

长度 是可选的,默认为数组的其余部分。

清单 可能是空的。

返回原始列表 长度 元素在 抵消.

在我们的示例中,如果有一个小快捷方式,我们将使用 清单:

子拼接{
我的 $self = shift;
我的 $offset = shift || 0;
我的 $length = shift || $self->FETCHSIZE() - $offset;
我的@list = ();
如果 ( @_ ) {
领带@list, __PACKAGE__, $self->{ELEMSIZE};
@列表=@_;
}
返回拼接@{$self->{ARRAY}}, $offset, $length, @list;
}

解开这个
当“untie”发生时将被调用。 (参见下面的“解开”陷阱。)

摧毁这个
当绑定变量需要销毁时,会触发该方法。 与
标量领带类,这在有自己的语言中几乎从不需要
垃圾收集,所以这次我们将把它排除在外。

搭售 哈希
散列是第一个被绑定的 Perl 数据类型(参见 数据库打开())。 一个类实现
绑定散列应该定义以下方法: TIEHASH 是构造函数。 取回和
STORE 访问键值对。 EXISTS 报告密钥是否存在于
hash,和 DELETE 删除一个。 CLEAR 通过删除所有键和值来清空哈希
对。 FIRSTKEY 和 NEXTKEY 实现 键()每个() 遍历所有的函数
按键。 SCALAR 在标量上下文中计算绑定散列时触发。 UNTIE是
当“untie”发生时调用,当绑定变量是垃圾时调用 DESTROY
集。

如果这看起来很多,那么可以随意继承标准 Tie::StdHash
大多数方法的模块,只重新定义有趣的方法。 见 Tie::Hash
细节。

请记住,Perl 区分散列中不存在的键和键
存在于散列中,但具有相应的“undef”值。 两种可能
可以使用“exists()”和“defined()”函数进行测试。

这是一个有点有趣的绑定散列类的例子:它给你一个散列
代表特定用户的点文件。 您使用以下名称对哈希进行索引
文件(减去点),你会得到那个点文件的内容。 例如:

使用点文件;
领带 %dot, 'DotFiles';
如果 ( $dot{profile} =~ /MANPATH/ ||
$dot{登录} =~ /MANPATH/ ||
$dot{cshrc} =~ /MANPATH/ )
{
打印 "你似乎设置了你的 MANPATH\n";
}

或者这里是使用绑定类的另一个示例:

领带 %him, 'DotFiles', 'daemon';
foreach $f ( 键 %him ) {
printf "守护进程点文件 %s 的大小为 %d\n",
$f, 长度 $hi{$f};
}

在我们的绑定散列 DotFiles 示例中,我们对包含多个对象的对象使用常规散列
重要字段,其中只有“{LIST}”字段是用户认为的
真正的哈希。

此对象表示其点文件的用户

那些点文件所在的家

克洛伯
我们是否应该尝试更改或删除那些点文件

LIST 点文件名和内容映射的散列

这是开始 点文件.pm:

打包点文件;
使用鲤鱼;
子哇西{(呼叫者(1))[3]。 '()' }
我的 $DEBUG = 0;
子调试{ $DEBUG = @_ ? 移位:1 }

对于我们的示例,我们希望能够发出调试信息以帮助跟踪
发展。 我们还在内部保留了一项便利功能以帮助打印
警告; 谁瓦西() 返回调用它的函数名。

以下是 DotFiles 绑定哈希的方法。

TIEHASH 类名,列表
这是类的构造函数。 这意味着它有望返回一个有福的
新对象通过它的引用(可能但不一定是匿名的
hash) 将被访问。

这是构造函数:

子 TIEHASH {
我的 $self = shift;
我的 $user = shift || $>;
我的 $dotdir = shift || '';
croak "用法:@{[&whowasi]} [USER [DOTDIR]]" 如果@_;
$user = getpwuid($user) 如果 $user =~ /^\d+$/;
我的 $dir = (getpwnam($user))[7]
|| croak "@{[&whowasi]}: 没有用户 $user";
$dir .= "/$dotdir" 如果 $dotdir;

我的 $node = {
用户 => $用户,
家 => $dir,
列表 => {},
CLOBBER => 0,
};

打开目录(目录,$ 目录)
|| croak "@{[&whowasi]}: 无法打开目录 $dir: $!";
foreach $dot ( grep /^\./ && -f "$dir/$_", readdir(DIR)) {
$点 =~ s/^\.//;
$node->{LIST}{$dot} = undef;
}
关闭目录;
返回祝福 $node, $self;
}

可能值得一提的是,如果您要对返回值进行文件测试
对于 readdir,你最好在有问题的目录前面加上。 否则,因为我们
没有 目录目录() 在那里,它会测试错误的文件。

获取这个,关键
每次访问绑定哈希中的元素时都会触发此方法
(读)。 它需要一个超出其自身引用的参数:我们所拥有的值的键
试图获取。

这是我们的 DotFiles 示例的提取。

子取回{
鲤鱼&whowasi if $DEBUG;
我的 $self = shift;
我的 $dot = shift;
我的 $dir = $self->{HOME};
我的 $file = "$dir/.$dot";

除非(存在 $self->{LIST}->{$dot} || -f $file){
鲤鱼“@{[&whowasi]}:没有 $dot 文件”如果 $DEBUG;
返回 undef;
}

如果(定义 $self->{LIST}->{$dot}){
返回 $self->{LIST}->{$dot};
} {
return $self->{LIST}->{$dot} = `cat $dir/.$dot`;
}
}

通过调用 Unix 很容易编写 (1) 命令,但它可能会
手动打开文件更便携(并且效率更高)。 当然,
因为点文件是 Unixy 的概念,所以我们并不担心。

存储这个,键,值
每次设置(写入)绑定散列中的元素时都会触发此方法。
除了它的自引用之外,它还有两个参数:我们试图找到的索引
存储一些东西,以及我们试图放在那里的价值。

在我们的 DotFiles 示例中,我们会小心不要让它们尝试覆盖
除非他们调用了文件 破坏者() 原始对象引用的方法
由...返回 领带().

子商店{
鲤鱼&whowasi if $DEBUG;
我的 $self = shift;
我的 $dot = shift;
我的 $value = shift;
我的 $file = $self->{HOME} 。 ”/.$点";
我的 $user = $self->{USER};

croak "@{[&whowasi]}: $file 不可破坏"
除非 $self->{CLOBBER};

打开(我的 $f, '>', $file) || croak "无法打开 $file: $!";
打印 $f $value;
关闭($ f);
}

如果他们想破坏某些东西,他们可能会说:

$ob = tie %daemon_dots, 'daemon';
$ob->破坏者(1);
$daemon_dots{signature} = "一个真正的守护进程\n";

另一种处理对底层对象的引用的方法是使用 绑()
函数,因此他们可能交替使用以下方法设置 clobber:

领带 %daemon_dots, '守护进程';
绑定(%daemon_dots)->破坏者(1);

clobber 方法很简单:

子破坏者{
我的 $self = shift;
$self->{CLOBBER} = @_ ? 移位:1;
}

删除这个,关键
当我们从散列中删除一个元素时会触发此方法,通常使用
删除() 功能。 再次,我们会仔细检查他们是否真的想要
破坏文件。

子删除{
鲤鱼&whowasi if $DEBUG;

我的 $self = shift;
我的 $dot = shift;
我的 $file = $self->{HOME} 。 ”/.$点";
croak "@{[&whowasi]}: 不会删除文件 $file"
除非 $self->{CLOBBER};
删除 $self->{LIST}->{$dot};
我的 $success = unlink($file);
carp "@{[&whowasi]}: 无法取消链接 $file: $!" 除非成功;
$成功;
}

DELETE 返回的值成为调用的返回值 删除()。 如果您
想要模仿正常行为 删除(), 你应该返回任何 FETCH
会返回这个键。 在这个例子中,我们选择返回一个
告诉调用者文件是否被成功删除的值。

清除这个
当整个散列要清除时触发此方法,通常通过分配
它的空列表。

在我们的示例中,这将删除所有用户的点文件! 这太危险了
他们必须将 CLOBBER 设置为高于 1 才能实现这一点。

子清除{
鲤鱼&whowasi if $DEBUG;
我的 $self = shift;
croak "@{[&whowasi]}: 不会删除 $self->{USER} 的所有点文件"
除非 $self->{CLOBBER} > 1;
我的 $dot;
foreach $dot ( 键 %{$self->{LIST}}) {
$self->DELETE($dot);
}
}

存在这个,关键
当用户使用 存在() 对特定的函数
哈希。 在我们的示例中,我们将查看“{LIST}”哈希元素:

子存在{
鲤鱼&whowasi if $DEBUG;
我的 $self = shift;
我的 $dot = shift;
返回存在 $self->{LIST}->{$dot};
}

FIRSTKEY 这个
当用户要遍历哈希时会触发此方法,例如
作为通过 键(), values()每个() 呼叫。

子 FIRSTKEY {
鲤鱼&whowasi if $DEBUG;
我的 $self = shift;
我的 $a = 键 %{$self->{LIST}}; # 重置 each() 迭代器
每个 %{$self->{LIST}}
}

FIRSTKEY 总是在标量上下文中调用,它应该只返回第一个键。
values()每个() 在列表上下文中,将为返回的键调用 FETCH。

NEXTKEY 这个,lastkey
这个方法在一个 键(), values()每个() 迭代。 它有一个
第二个参数是已访问的最后一个键。 这很有用,如果
您关心从多个序列中排序或调用迭代器,或者
没有真正将东西存储在任何地方的哈希中。

NEXTKEY 总是在标量上下文中调用,它应该只返回下一个键。
values()每个() 在列表上下文中,将为返回的键调用 FETCH。

对于我们的示例,我们使用的是真正的散列,因此我们将只做简单的事情,但我们将
必须间接通过 LIST 字段。

子下一个键{
鲤鱼&whowasi if $DEBUG;
我的 $self = shift;
返回每个 %{ $self->{LIST} }
}

标量这个
当在标量上下文中计算散列时会调用它。 为了模仿
未绑定散列的行为,当绑定散列时,此方法应返回假值
被认为是空的。 如果这个方法不存在,perl 会让一些受过教育的
当散列在迭代中时,猜测并返回真。 如果不是这种情况,
FIRSTKEY 被调用,如果 FIRSTKEY 返回空,结果将是一个假值
列表,否则为真。

但是,你应该 而不去 一味地依赖perl 总是做正确的事。
特别是,当你反复清除散列时,perl 会错误地返回 true
调用 DELETE 直到它为空。 因此,建议您提供自己的 SCALAR
当您想绝对确定您的哈希在标量中表现良好时的方法
上下文。

在我们的示例中,我们可以在引用的底层哈希上调用“标量”
“$self->{LIST}”:

子标量{
鲤鱼&whowasi if $DEBUG;
我的 $self = shift;
返回标量 %{ $self->{LIST} }
}

解开这个
这在“解开”发生时被调用。 请参阅下面的“解开”陷阱。

摧毁这个
当绑定的散列即将超出范围时触发此方法。 你不
除非您尝试添加调试或需要清理辅助状态,否则真的需要它
向上。 这是一个非常简单的函数:

子销毁{
鲤鱼&whowasi if $DEBUG;
}

请注意,函数如 键()values() 用于大型列表时可能会返回巨大的列表
对象,如 DBM 文件。 您可能更喜欢使用 每个() 函数来迭代这样的。
示例:

# 打印历史文件偏移量
使用 NDBM_File;
领带(%HIST, 'NDBM_File', '/usr/lib/news/history', 1, 0);
而 (($key,$val) = 每个 %HIST) {
打印 $key, ' = ', unpack('L',$val), "\n";
}
解开(%HIST);

搭售 文件句柄
现在已部分实施。

实现绑定文件句柄的类应该定义以下方法: TIEHANDLE, at
PRINT、PRINTF、WRITE、READLINE、GETC、READ 以及可能的 CLOSE、UNTIE 和
破坏。 该类还可以提供:BINMODE、OPEN、EOF、FILENO、SEEK、TELL - 如果
句柄上使用了相应的 perl 运算符。

当 STDERR 被绑定时,其 PRINT 方法将被调用以发出警告和错误消息。
此功能在通话过程中暂时禁用,这意味着您可以使用“warn()”
在 PRINT 内部而不启动递归循环。 就像“__WARN__”和“__DIE__”
处理程序,可能会调用 STDERR 的 PRINT 方法来报告解析器错误,因此需要注意
perlvar 中的“%SIG”下提到的应用。

当 perl 嵌入到其他程序中时,所有这些都特别有用,其中输出
到 STDOUT 和 STDERR 可能必须以某种特殊方式重定向。 参见 nvi 和
Apache 模块示例。

绑定句柄时,“tie”的第一个参数应以星号开头。 因此,如果
您正在绑定 STDOUT,请使用 *STDOUT。 如果您已将其分配给标量变量,请说
$handle,使用*$handle。 "tie $handle" 绑定标量变量 $handle,而不是句柄
在里面。

在我们的示例中,我们将创建一个喊叫句柄。

包喊;

TIEHANDLE 类名,列表
这是类的构造函数。 这意味着它有望返回一个有福的
某种形式的参考。 该引用可用于保存一些内部信息。

子领带{打印“ \n"; 我的 $i; 保佑 \$i, shift }

写这个,清单
当通过“syswrite”函数写入句柄时,将调用此方法。

子写{
$r = 移位;
我的($buf,$len,$offset) = @_;
打印 "WRITE 调用,\$buf=$buf,\$len=$len,\$offset=$offset";
}

打印这个,列表
每次打印绑定的句柄时都会触发此方法
“print()”或“say()”函数。 除了它的自引用之外,它还期望列表
传递给打印函数。

sub PRINT { $r = shift; $$r++; 打印 join($,,map(uc($_),@_)),$\ }

“say()”就像“print()”一样,除了 $\ 将被本地化为“\n”,所以你需要做
处理“PRINT()”中的“say()”没有什么特别之处。

打印这个,列表
每次打印绑定的句柄时都会触发此方法
“printf()”函数。 除了它的自引用之外,它还需要格式和列表
传递给 printf 函数。

子打印{
转移;
我的 $fmt = shift;
打印 sprintf($fmt, @_);
}

阅读这个,列出
当通过“read”或“sysread”读取句柄时将调用此方法
功能。

子阅读{
我的 $self = shift;
我的 $bufref = \$_[0];
我的(undef,$len,$offset) = @_;
打印“读取调用,\$buf=$bufref,\$len=$len,\$offset=$offset”;
# 添加到 $$bufref,设置 $len 为读取的字符数
$len;
}

阅读此内容
当通过“读取句柄”时调用此方法" 或 "readline 句柄"。

根据“readline”,在标量上下文中,它应该返回下一行,或者“undef”表示没有
更多数据。 在列表上下文中,它应该返回所有剩余的行,或者一个空列表
没有更多的数据。 返回的字符串应包括输入记录分隔符 $/(请参阅
perlvar),除非它是“undef”(这意味着“slurp”模式)。

子阅读{
我的 $r = 班次;
如果(想要数组){
return ("所有剩余\n",
"排队\n",
"到eof\n");
} {
返回“READLINE 调用”。 ++$$r 。 " 次\n";
}
}

得到这个
当调用“getc”函数时将调用此方法。

子GETC { 打印“不要GETC,获取Perl”; 返回“一个”; }

EOF这个
当调用“eof”函数时将调用此方法。

从 Perl 5.12 开始,将传递一个额外的整数参数。 这将是
如果在没有参数的情况下调用“eof”,则为零; 1 如果给“eof”一个文件句柄作为
参数,例如“eof(FH)”; 和 2 在非常特殊的情况下,绑定的文件句柄是
"ARGV" 和 "eof" 使用空参数列表调用,例如 "eof()"。

sub EOF { 不是长度 $stringbuf }

关闭这个
当通过“close”函数关闭句柄时,将调用此方法。

sub CLOSE { 打印“调用 CLOSE。\n”}

解开这个
与其他类型的关系一样,当“解开”发生时将调用此方法。 它
发生这种情况时,可能适合“自动关闭”。 请参阅下面的“解开”陷阱。

摧毁这个
与其他类型的领带一样,当被绑的手柄处于
即将被摧毁。 这对于调试和可能的清理很有用。

子销毁{打印“ \n" }

下面是如何使用我们的小例子:

领带(*FOO,'喊');
打印 FOO "你好\n";
$a = 4; $b = 6;
打印 FOO $a, " plus ", $b, " equals ", $a + $b, "\n";
打印;

解开 Free Introduction
您可以为所有关系类型定义一个将在以下位置调用的 UNTIE 方法 解开(). 见“
在下面“解开”陷阱”。

这款 “解开” 疑难杂症
如果您打算使用从任一返回的对象 领带() or 绑(),如果
tie 的目标类定义了一个析构函数,你有一个微妙的问题 必须 防止。

作为设置,请考虑这个(无可否认相当人为的)领带示例; 它所做的就是使用
一个文件,用于保存分配给标量的值的日志。

包记住;

用严格;
使用警告;
使用 IO::File;

子 TIESCALAR {
我的 $class = shift;
我的 $filename = shift;
我的 $handle = IO::File->new( "> $filename" )
或者死“无法打开 $filename: $!\n”;

print $handle "The Start\n";
祝福 {FH => $handle, Value => 0}, $class;
}

子取回{
我的 $self = shift;
返回 $self->{Value};
}

子商店{
我的 $self = shift;
我的 $value = shift;
我的 $handle = $self->{FH};
打印 $handle "$value\n";
$self->{Value} = $value;
}

子销毁{
我的 $self = shift;
我的 $handle = $self->{FH};
打印 $handle "The End\n";
关闭 $handle;
}

1;

下面是一个利用这种关系的例子:

用严格;
使用记住;

我的 $fred;
领带 $fred, '记住', 'myfile.txt';
$弗雷德= 1;
$弗雷德= 4;
$弗雷德= 5;
解开 $fred;
系统“cat myfile.txt”;

这是执行时的输出:

开始
1
4
5


到现在为止还挺好。 一直关注的小伙伴会发现
目前还没有使用绑定对象。 所以让我们向记住类添加一个额外的方法
允许在文件中包含注释; 说,像这样:

子评论{
我的 $self = shift;
我的 $text = shift;
我的 $handle = $self->{FH};
打印 $handle $text, "\n";
}

这是前面的示例修改为使用“评论”方法(这需要
绑定对象):

用严格;
使用记住;

我的 ($fred, $x);
$x = tie $fred, '记住', 'myfile.txt';
$弗雷德= 1;
$弗雷德= 4;
评论 $x "正在改变...";
$弗雷德= 5;
解开 $fred;
系统“cat myfile.txt”;

执行此代码时,没有输出。 原因如下:

当一个变量被绑定时,它与作为返回值的对象相关联
TIESCALAR、TIEARRAY 或 TIEHASH 函数。 这个对象通常只有一个引用,
即,来自绑定变量的隐式引用。 什么时候 解开() 被称为
引用被破坏。 然后,如上面的第一个例子,对象的析构函数
(DESTROY) 被调用,这对于没有更多有效引用的对象来说是正常的; 和
因此文件被关闭。

然而,在第二个例子中,我们在 $x 中存储了另一个对绑定对象的引用。
这意味着当 解开() 被调用仍然会有一个有效的引用
对象存在,所以当时不会调用析构函数,因此文件是
没有关闭。 没有输出的原因是因为文件缓冲区没有被
刷新到磁盘。

既然您知道问题出在哪里,您可以做些什么来避免它? 在...之前
引入可选的 UNTIE 方法的唯一方法是使用旧的“-w”标志。 哪个
将发现您调用的任何实例 解开() 并且仍然有对
绑定的对象。 如果上面靠近顶部的第二个脚本“使用警告'解开'”或者是
使用“-w”标志运行,Perl 打印此警告消息:

在 1 个内部引用仍然存在时尝试解开

要使脚本正常工作并使警告静音,请确保没有有效的
对绑定对象的引用 before 解开() 叫做:

未定义 $x;
解开 $fred;

现在 UNTIE 存在,类设计者可以决定类功能的哪些部分
真正与“解开”相关联,并且与被销毁的对象相关联。 是什么使得
给定类的意义取决于是否保留了内部引用,以便
可以在对象上调用非绑定相关的方法。 但在大多数情况下,它可能会使
将 DESTROY 中的功能移动到 UNTIE 方法是有意义的。

如果存在 UNTIE 方法,则不会出现上述警告。 取而代之的是 UNTIE 方法
传递“额外”引用的计数,并且可以在适当时发出自己的警告。
例如,要复制没有 UNTIE 的情况,可以使用此方法:

子UNTIE
{
我的 ($obj,$count) = @_;
鲤鱼“在 $count 内部引用仍然存在的情况下尝试解绑”如果 $count;
}

使用 onworks.net 服务在线使用 perltie


免费服务器和工作站

下载 Windows 和 Linux 应用程序

  • 1
    电影启动器
    电影启动器
    Kodi Movistar+ TV 是 XBMC/ 的 ADDON
    Kodi 许可分配器
    IPTV服务解码器
    Movistar Integrado en uno de los
    媒体中心马...
    下载 movistartv
  • 2
    代码::块
    代码::块
    Code::Blocks 是一个免费的、开源的、
    跨平台 C、C++ 和 Fortran IDE
    专为满足最苛刻的需求而打造
    它的用户。 它的设计非常
    扩展...
    下载代码::Blocks
  • 3
    之中
    之中
    中间或高级 Minecraft 界面
    和数据/结构跟踪是一种工具
    显示 Minecraft 的概览
    世界,而无需实际创造它。 它
    能够 ...
    下载烟雨
  • 4
    系统2
    系统2
    MSYS2 是一组工具和
    图书馆为您提供
    易于使用的建筑环境,
    安装和运行本机 Windows
    软件。 它连...
    下载 MSYS2
  • 5
    libjpeg-turbo
    libjpeg-turbo
    libjpeg-turbo 是一个 JPEG 图像编解码器
    使用 SIMD 指令(MMX、SSE2、
    NEON、AltiVec)加速基线
    JPEG 压缩和解压
    x86、x8...
    下载 libjpeg-turbo
  • 6
    Xtreme下载管理器
    Xtreme下载管理器
    该项目现在有了一个新家:
    https://xtremedownloadmanager.com/ For
    开发人员:
    https://github.com/subhra74/xdm Xtreme
    下载管理器是一个强大的工具...
    下载 Xtreme 下载管理器
  • 更多 ”

Linux 命令

Ad