[英]How to organize private methods on Perl objects?
處理用戶不會調用的方法的正確方法是什么? 例如,如果用戶調用方法,例如從驅動程序腳本中調用do_stuff()
,並且do_stuff()
依賴於其他子例程,那么最好從do_stuff()
方法中調用這些subs,如下所示:
sub do_stuff {
my ( $self, %arg ) = @_;
#does it things
#and then calls the private sub as follows
_private_sub( $self, %arg );
}
據我所知,沒有“正確”的方式。 Perl不提供隱藏功能的能力,至少我曾遇到過這種功能。 我所做的是使用命名標准,我用一個下划線啟動僅內部函數名稱,並清楚地記錄它們永遠不會被外部調用者調用。
編輯:其他答案引發了一個想法。 在每個私有方法中,您可以檢查“caller()”函數的結果,如果調用者是本地模塊以外的任何人,則中止。 老實說,我個人不會遇到麻煩,但如果由於某種原因它對你來說真的很重要,那就會強調這些方法的私人性質。
如果你的do_stuff
方法需要你決定應該保持“私有”的功能,那么一定要在其中調用_private_sub
。 這正是它的目的。 當然,將子“私有”是一個慣例問題,因為它無法執行。
我想提一下使用coderefs進行私有子的另一種方式
my $_private = sub { ... }; # must be at least predeclared
sub do_stuff {
my ($self, %arg) = @_;
# ...
my $from_private = $self->$_private->(@args); # or
my $more_private = $_private->($self, @args);
}
語法很奇怪,但肯定會警告用戶它是一個私有方法。 這使得子類很難繼承,這要歸功於mob強調這一點。
第二次調用使用$_private
作為函數而不是方法,因此我們必須在需要時傳遞對象。 這進一步警告不要使用它。 然后它也沒有經歷正常的方法查找過程(因此稍微快一點),這是一個很好的意識。
關於究竟是什么問題,我有點不確定。
如果是關於是否在代碼中使用“私有”子程序,那么實際上沒有公認的最佳實踐。 它們非常有用,但它們並非真正私密。 我自由地使用它們。
而不是$self->_private_sub(...)
? 在我看來, $obj->_method
表示法總是與作用於類實例的函數一起使用,其他類型的調用總是用於其他類型的函數。
但是,如果你是偏執狂,為什么不使用一種非傳統的方式來填充你的論點,這會讓那些試圖以面向對象的方式使用私有方法的人感到困惑?
sub do_stuff {
my ( $self, %arg ) = @_;
...
_private_sub( %arg, $self );
}
sub _private_sub {
my $self = pop;
my %args = @_;
...
}
到目前為止,您收到的所有答案都表示無法完成。 但它可以 - 在Perl 5.18及更高版本中。 請參閱perldoc perlsub
有關詞perldoc perlsub
例程的部分 。
詞法子程序
警告:詞法子程序仍處於試驗階段。 在將來的Perl版本中可能會修改或刪除該功能。
詞法子例程僅在
use feature 'lexical_subs'
編譯指示下可用,除非禁用“experimental :: lexical_subs”警告類別,否則它會產生警告。從Perl 5.18開始,您可以使用
my
或state
聲明私有子例程。 與狀態變量一樣,state關鍵字僅在use feature 'state'
下可用或use 5.010
或更高版本。這些子例程僅在聲明它們的塊中可見,並且僅在聲明之后:
no warnings "experimental::lexical_subs"; use feature 'lexical_subs'; foo(); # calls the package/global subroutine state sub foo { foo(); # also calls the package subroutine } foo(); # calls "state" sub my $ref = \\&foo; # take a reference to "state" sub my sub bar { ... } bar(); # calls "my" sub
要從子例程本身內部使用詞法子例程,必須預先聲明它。
sub foo {...}
子例程定義語法尊重任何先前的my sub;
或state sub;
宣言。my sub baz; # predeclaration sub baz { # define the "my" sub baz(); # recursive call }
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.