36

私は小さなPerlモジュールに取り組んでおり、何らかの理由で、新しいモジュールを使用していたテストドライバースクリプトが、プライベートだと思っていた関数の1つを呼び出し、成功しました。驚いたので、グーグルを検索し始めましたが、Perlモジュールでプライベート関数を作成する方法に関するドキュメントを実際に見つけることができませんでした...

次のように、「プライベート」関数の閉じ中括弧の後にセミコロンを付けると言われている場所を見ました。

sub my_private_function {
...
}; 

私はそれを試しましたが、私のドライバースクリプトは、私がプライベートにしたい関数にアクセスできました。

短い例になるようなものを作りますが、私が求めているのは次のとおりです。

モジュールTestPrivate.pm:

package TestPrivate;

require 5.004;

use strict;
use warnings;
use Carp;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);

require Exporter;

@ISA = qw(Exporter AutoLoader);

our @EXPORT_OK = qw( public_function );
our @EXPORT    = qw( );

$VERSION = '0.01';

sub new {
    my ( $class, %args ) = @_;
    my $self = {};
    bless( $self, $class );
    $self->private_function("THIS SHOULD BE PRIVATE");
    $self->{public_variable} = "This is public";
    return $self;
}

sub public_function {
    my $self     = shift;
    my $new_text = shift;
    $self->{public_variable} = $new_text;
    print "Public Variable: $self->{public_variable}\n";
    print "Internal Variable: $self->{internal_variable}\n";
}

sub private_function {
    my $self     = shift;
    my $new_text = shift;
    $self->{internal_variable} = $new_text;
}

ドライバー:TestPrivateDriver.pl

#!/usr/bin/perl
use strict;
use TestPrivate 'public_function';
my $foo = new TestPrivate();
$foo->public_function("Changed public variable");
$foo->private_function("I changed your private variable");
$foo->public_function("Changed public variable again");
$foo->{internal_variable} = "Yep, I changed your private variable again!";
$foo->public_function("Changed public variable the last time");

ドライバー出力:

Public Variable: Changed public variable
Internal Variable: THIS SHOULD BE PRIVATE
Public Variable: Changed public variable again
Internal Variable: I changed your private variable
Public Variable: Changed public variable the last time
Internal Variable: Yep, I changed your private variable again!

そのため、モジュールの最後の閉じ中括弧の後にセミコロンを追加しましたが、出力は同じです。私が実際に見つけた唯一のことは、この行を私のprivate_functionの最初の行として追加することでした。

caller eq __PACKAGE__ or die;

しかし、それはかなりハッキーなようです。私はPerlモジュールを書いた経験があまりないので、モジュールを間違って設定しているのではないでしょうか?perlモジュールにプライベート関数と変数を含めることは可能ですか?

私が学ぶのを手伝ってくれてありがとう!

4

9 に答える 9

38

からperldoc perltoot(ドキュメントの約4分の1の方法):

Perlは、誰がどのメソッドを使用できるかについて制限を課していません。パブリックとプライベートの区別は、構文ではなく、慣例によるものです。(以下の「変数としてのデータメンバー」で説明されているAliasモジュールを使用しない限り。)場合によっては、メソッド名が1つまたは2つのアンダースコアで開始または終了することがあります。このマーキングは、メソッドがそのクラスだけにプライベートであり、場合によっては最も近い知人であるその直接のサブクラスにプライベートであることを示す規則です。しかし、この区別はPerl自体によって強制されるものではありません。振る舞うのはプログラマー次第です。

したがって、使用を思いとどまらせるために、「プライベート」メソッドの先頭に1つまたは2つのアンダースコアを付けることをお勧めします。

于 2009-01-16T19:09:02.990 に答える
23

コード参照を字句変数に格納する「TheKludge」のみがあり、そのスコープ外の誰も見ることができません。

my $priv_func1 = sub { my $self = shift; say 'func1'; };

sub public_sub { 
    my $self = shift;

    $priv_func1->( $self );
}

そして、厳密に「保護された」フィールドを作成する方法を考えることはできません。

私の知る限りではこれで終わりです(ソースフィルター以外に...shhhh。言及しませんでした...)


編集:実際、私は保護された非常に厄介な方法を考えることができます。AUTOLOADしかし、それはおそらくすべての呼び出しを潜水艦に通すことを伴うでしょう。(!!)

于 2009-01-16T19:10:19.243 に答える
15

これは機能します:

my $priv_func1 = sub {
    my $self = shift; say 'func1';
};

sub public_sub { 
    my $self = shift;

    $self->$priv_func1(@_);
}
于 2009-01-17T00:50:06.000 に答える
6

あなたは何をしようとしているのですか?あなたが達成しようとしていることは何でも、より良い Perl の方法があるかもしれません。

たとえば、カプセル化を強制したいためにオブジェクトをいじりたくない場合は、Class::InsideOutのようなものを使用できます。そのモジュールには、概念を説明する Class::InsideOut::About ドキュメント モジュールがあります。ブライアン・フィリップスがすでに言及したObject::InsideOutもあります。

于 2009-01-16T21:28:52.457 に答える
3

以下のperlプライベート関数に何かを記述して、caller[0]givesパッケージと同じobjからの呼び出しを確認できます。

sub foo {
  my ($s, %args) = @_;
  die "Error: Private method called"
      unless (caller)[0]->isa( ref($s) );
}
于 2009-05-15T05:43:52.683 に答える
3

このスタイルの OO は、しばらくすると、Data::Dumper を使用してオブジェクトを直接ダンプしたり、オブジェクトの内部を覗いてそのデータを確認したりできないことに気付くと、少し「不自然」に感じ始めます。ただし、試してみたい場合は、 Object::InsideOutを使用することをお勧めします。他の多くの便利な機能 (アクセサー生成、デフォルト コンストラクターなど) と共に、オブジェクトのプライベート データとメソッドをサポートします。

于 2009-01-16T19:43:07.040 に答える
2

Mooseのようなシステムを使用する場合は、ここに示すように公開/非公開の区別を得ることができます

于 2009-05-15T21:42:14.363 に答える
0

パッケージのファイル: プライベート メソッドを CODE-Ref として定義します。

my $private_methode = sub{};
于 2015-01-19T10:20:16.567 に答える