我正在玩現有的 perl 模塊,我們稱之為 Obj。我向 Obj 添加了一些新功能(子例程/方法),但將它們存盤在另一個 .pm 中,稱之為 Foo。但是我不希望 Obj 從 Foo 繼承每個子。
現在我已經閱讀了幾個小時的 perl 檔案并且很困惑。 https://perldoc.perl.org/Exporter#Selecting-What-to-Export 只是說“不要匯出方法名稱!”
這是一些示例代碼,我不想看到來自 Obj.pm 的子 _not_exported:
#!/usr/bin/env perl
use strict;
use warnings;
use diagnostics;
#https://docstore.mik.ua/orelly/perl2/prog/ch12_05.htm
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 等其他選項持開放態度,但不想過多地更改舊代碼。提前致謝
uj5u.com熱心網友回復:
[注意:我是 Exporter 的前維護者]
我相信您已經將匯出與繼承混淆了。這很容易做到,Perl 沒有在“函式”和“方法”之間劃清界限,它們只是sub.
tl; dr您不需要匯出,這就是繼承的作業方式,有一種解決方法。
匯出允許您從包外部呼叫函式,而無需完全限定它。它會讓你打電話Foo::hello。hello匯出讓 Perl 知道這hello實際上意味著hello在 package 中Foo。
但這些是方法呼叫,您可以在類或物件上呼叫它們。my $foo = Foo->new; $foo->hello. 無需匯出。Foo->new呼叫new并Foo回傳一個Foo物件。知道在類的祖先中$foo->hello尋找方法。您不需要在類中使用匯出器,這就是“不要匯出方法名稱”的意思。foo$foo
匯出是一種故意復制符號的行為。繼承是全部或全部。如果你從一個類繼承,你會得到它的所有方法(subs)。這是繼承的結果,還有許多其他的繼承替代方案,例如組合。
在其他 OO 語言中,您可以宣告該方法private并且它不會被繼承。Perl 沒有。通常你只是按照慣例接受這個,在方法名稱前加一個下劃線,不要記錄它,如果有人使用它,那就是他們的問題。這通常很好。
但是您可以使用匿名子和詞法變數創建真正的私有方法。
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 繼承newandhello和public_methodfrom Foo,但它看不到 $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的實體作業。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/419516.html
標籤:
下一篇:InvalidArgumentError:logits和標簽必須具有相同的第一維,得到logits形狀[15488,3]和標簽形狀[32]
