如何不从 perl 中的包中导出所有 functions/methods?
How to not export all functions/methods from a package in perl?
我正在玩弄一个现有的 perl 模块,我们称它为 Obj。
我向 Obj 添加了一些新功能(子例程/方法),但将它们存储在另一个 .pm 中,称之为 Foo。但是我不希望 Obj 继承 Foo 的每个子项。
现在我已经阅读了几个小时的 perl 文档并且感到困惑。
https://perldoc.perl.org/Exporter#Selecting-What-to-Export
只是说 'Do not export method names!'
这是一些示例代码,我不想看到来自 Obj.pm 的子 _not_exported:
#!/usr/bin/env perl
use strict;
use warnings;
use diagnostics;
package Foo;# Foo is a new PM file used to extend Obj with collections of subroutine's.
# I want to use hello() from Obj
#use Exporter 'import';
use Exporter qw(import);
our @EXPORT_OK = qw/hello/;
sub hello {
my $self = shift;
$self->{test} = 'Hello world';
}
# I'd rather not pollute Obj with this sub
# or perfreably all subs the begin with a underscore
# How do I exclude this sub?
sub _not_exported {
my $self = shift;
return 'Exported';
}
#main old code object module
package Obj; # large old PM file I dont want to change this file much
# pull in the new module
use base 'Foo';
# use base seems better than this:
#import Foo;
#our @ISA = qw(Foo);
sub new {
my $self = {};
bless $self, 'Obj';
return $self;
}
eval { $this = $form->_not_exported() } ; #Should return nothing
sub catch_hash {
my ($self,$arg) = @_;
$arg |= '';
$self->{test} = 'catch';
}
#Perl script, creates an object using Obj;
package main;
#use Obj;
import Obj;
my $form = Obj->new();
$form->catch_hash();
print "Toss? '$form->{test}' \n";
$form->hello();
print "\nHello? '$form->{test}'\n";
my $this = "";
eval { $this = $form->_not_exported() } ; #Should return nothing
print "$this\ndone\n";
1;
我对 Moo / Moose 等其他选项持开放态度,但不想对旧代码进行太多更改。
提前致谢
[注意:我是 Exporter 的前维护者]
我相信您混淆了导出和继承。这很容易做到,Perl 不会在“函数”和“方法”之间划一条线,它们只是 sub
.
tl;dr 你不需要导出,这就是继承的工作方式,有一个解决方法。
导出允许您从包外部调用函数而无需完全限定它。它会让你调用 Foo::hello
就像 hello
一样。导出让 Perl 知道 hello
真正意味着包 Foo
.
中的 hello
但这些是方法调用,您可以在 class 或对象上调用它们。 my $foo = Foo->new; $foo->hello
。无需导出。 Foo->new
在 Foo
和 returns 中调用 new
一个 Foo
对象。 $foo->hello
知道在 $foo
的 class 的祖先中寻找方法 foo
。您不需要在 class 中使用导出器,这就是“不导出方法名称”的意思。
导出是一种故意复制符号的行为。继承是全有或全无。如果您从 class 继承,您将获得它的所有方法(subs)。这是继承的结果,还有许多其他继承替代方案,例如 composition.
在其他 OO 语言中,您可以声明方法 private
并且它不会被继承。 Perl 没有那个。通常你只是按照惯例接受这个,在方法名称前加一个下划线,不要记录它,如果有人使用它那是他们的问题。这通常没问题。
但是您可以使用 anonymous subs and lexical variables 来创建真正私有的方法。
package Foo;
# Define `new` in Foo. Obj will inherit it.
# Do not hard code the class.
# `new` receives the class new was called on.
sub new {
my $class = shift;
return bless {}, $class;
}
sub hello {
my $self = shift;
$self->{test} = 'Hello world';
}
# This is a reference to an anonymous function in a lexical variable.
# It can only be seen by the code after this line in this file.
my $private_method = sub {
my $self = shift;
return "private method called by $self with args: @_\n";
};
sub public_method {
my $self = shift;
# $private_method can be seen here.
# A subroutine reference can be called like a method.
print $self->$private_method("basset hounds got long ears");
}
并且在Obj.pm
package Obj;
# parent is a lightweight replacement for base.
use parent 'Foo';
Obj 从 Foo
继承了 new
和 hello
以及 public_method
,但它看不到 $private_method。只能在Foo.pm.
里面看到
my $obj = Obj->new;
# private method called by Obj=HASH(0x7fcfdb8126d8) with args: basset hounds got long ears
$obj->public_method;
因为 public_method
是在它可以看到 $private_method
的地方定义的,所以 $obj->public_method
尽管是在 Obj 而不是 Foo 的实例上调用的,但仍然可以工作。
我正在玩弄一个现有的 perl 模块,我们称它为 Obj。 我向 Obj 添加了一些新功能(子例程/方法),但将它们存储在另一个 .pm 中,称之为 Foo。但是我不希望 Obj 继承 Foo 的每个子项。
现在我已经阅读了几个小时的 perl 文档并且感到困惑。 https://perldoc.perl.org/Exporter#Selecting-What-to-Export 只是说 'Do not export method names!'
这是一些示例代码,我不想看到来自 Obj.pm 的子 _not_exported:
#!/usr/bin/env perl
use strict;
use warnings;
use diagnostics;
package Foo;# Foo is a new PM file used to extend Obj with collections of subroutine's.
# I want to use hello() from Obj
#use Exporter 'import';
use Exporter qw(import);
our @EXPORT_OK = qw/hello/;
sub hello {
my $self = shift;
$self->{test} = 'Hello world';
}
# I'd rather not pollute Obj with this sub
# or perfreably all subs the begin with a underscore
# How do I exclude this sub?
sub _not_exported {
my $self = shift;
return 'Exported';
}
#main old code object module
package Obj; # large old PM file I dont want to change this file much
# pull in the new module
use base 'Foo';
# use base seems better than this:
#import Foo;
#our @ISA = qw(Foo);
sub new {
my $self = {};
bless $self, 'Obj';
return $self;
}
eval { $this = $form->_not_exported() } ; #Should return nothing
sub catch_hash {
my ($self,$arg) = @_;
$arg |= '';
$self->{test} = 'catch';
}
#Perl script, creates an object using Obj;
package main;
#use Obj;
import Obj;
my $form = Obj->new();
$form->catch_hash();
print "Toss? '$form->{test}' \n";
$form->hello();
print "\nHello? '$form->{test}'\n";
my $this = "";
eval { $this = $form->_not_exported() } ; #Should return nothing
print "$this\ndone\n";
1;
我对 Moo / Moose 等其他选项持开放态度,但不想对旧代码进行太多更改。 提前致谢
[注意:我是 Exporter 的前维护者]
我相信您混淆了导出和继承。这很容易做到,Perl 不会在“函数”和“方法”之间划一条线,它们只是 sub
.
tl;dr 你不需要导出,这就是继承的工作方式,有一个解决方法。
导出允许您从包外部调用函数而无需完全限定它。它会让你调用 Foo::hello
就像 hello
一样。导出让 Perl 知道 hello
真正意味着包 Foo
.
hello
但这些是方法调用,您可以在 class 或对象上调用它们。 my $foo = Foo->new; $foo->hello
。无需导出。 Foo->new
在 Foo
和 returns 中调用 new
一个 Foo
对象。 $foo->hello
知道在 $foo
的 class 的祖先中寻找方法 foo
。您不需要在 class 中使用导出器,这就是“不导出方法名称”的意思。
导出是一种故意复制符号的行为。继承是全有或全无。如果您从 class 继承,您将获得它的所有方法(subs)。这是继承的结果,还有许多其他继承替代方案,例如 composition.
在其他 OO 语言中,您可以声明方法 private
并且它不会被继承。 Perl 没有那个。通常你只是按照惯例接受这个,在方法名称前加一个下划线,不要记录它,如果有人使用它那是他们的问题。这通常没问题。
但是您可以使用 anonymous subs and lexical variables 来创建真正私有的方法。
package Foo;
# Define `new` in Foo. Obj will inherit it.
# Do not hard code the class.
# `new` receives the class new was called on.
sub new {
my $class = shift;
return bless {}, $class;
}
sub hello {
my $self = shift;
$self->{test} = 'Hello world';
}
# This is a reference to an anonymous function in a lexical variable.
# It can only be seen by the code after this line in this file.
my $private_method = sub {
my $self = shift;
return "private method called by $self with args: @_\n";
};
sub public_method {
my $self = shift;
# $private_method can be seen here.
# A subroutine reference can be called like a method.
print $self->$private_method("basset hounds got long ears");
}
并且在Obj.pm
package Obj;
# parent is a lightweight replacement for base.
use parent 'Foo';
Obj 从 Foo
继承了 new
和 hello
以及 public_method
,但它看不到 $private_method。只能在Foo.pm.
my $obj = Obj->new;
# private method called by Obj=HASH(0x7fcfdb8126d8) with args: basset hounds got long ears
$obj->public_method;
因为 public_method
是在它可以看到 $private_method
的地方定义的,所以 $obj->public_method
尽管是在 Obj 而不是 Foo 的实例上调用的,但仍然可以工作。