/ / Wie erstelle ich private Funktionen in einem Perl-Modul? - Perl, Modul, Perl-Modul, Private-Funktionen

Wie erstelle ich private Funktionen in einem Perl-Modul? - Perl, Modul, Perl-Modul, Private-Funktionen

Ich arbeite an einem kleinen Perl-Modul und für einigeGrund dafür war, dass das Testtreiberskript, das mein neues Modul verwendete, eine der Funktionen aufrief, von denen ich dachte, dass sie privat sind, und es war erfolgreich. Ich war überrascht, also habe ich angefangen, nach Google zu suchen und konnte keine Dokumentation darüber finden, wie man private Funktionen in Perl-Modulen erstellt ...

Ich habe eine Stelle gesehen, an der nach dem Abschluss Ihrer "privaten" Funktion ein Semikolon steht:

sub my_private_function {
...
};

Ich habe das versucht, aber mein Treiberskript konnte immer noch auf die Funktion zugreifen, die ich privat haben wollte.

Ich werde etwas erfinden, das ein kürzeres Beispiel sein wird, aber hier ist, was ich danach bin:

Modul 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;
}

Treiber: 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");

Treiberausgabe:

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!

Also habe ich nach der letzten schließenden Klammer im Modul ein Semikolon eingefügt, aber die Ausgabe ist immer noch dieselbe. Das einzige, was ich wirklich gefunden habe, war, diese Zeile als erste Zeile zu meiner private_function hinzuzufügen:

caller eq __PACKAGE__ or die;

Aber das scheint ziemlich abgedreht zu sein. Ich habe nicht viel Erfahrung mit dem Schreiben von Perl-Modulen. Vielleicht richte ich mein Modul falsch ein. Ist es möglich, private Funktionen und Variablen in Perl-Modulen zu haben?

Danke, dass du mir geholfen hast zu lernen!

Antworten:

33 für die Antwort № 1

Von perldoc perltoot (ungefähr ein viertel Weg durch das Dokument):

Perl schränkt nicht ein, wer ankommtbenutze welche Methoden. Das Die Unterscheidung zwischen öffentlich und privat erfolgt nach Konvention, nicht nach der Syntax. (Gut, es sei denn, Sie verwenden das unten unter "Datenelemente als" beschriebene Alias-Modul Variablen ".) Gelegentlich werden Methodennamen angezeigt, die mit beginnen oder enden ein oder zwei Unterstriche. Diese Kennzeichnung ist eine Konvention, die angibt, dass die Methoden sind nur für diese Klasse und manchmal für die nächstgelegene privat Bekannte, seine unmittelbaren Unterklassen. Aber diese Unterscheidung ist nicht von Perl selbst erzwungen. Es liegt an dem Programmierer, sich zu verhalten.

Aus diesem Grund empfehle ich Ihnen, ein oder zwei Unterstriche am Anfang Ihrer "privaten" Methoden zu setzen, um die Verwendung zu verhindern.


21 für die Antwort № 2

Es gibt nur "The Kludge" zum Speichern einer Codereferenz in einer lexikalischen Variablen, die niemand außerhalb dieses Bereichs sehen kann:

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

sub public_sub {
my $self = shift;

$priv_func1->( $self );
}

Und ich kann nicht denken eine Möglichkeit, streng "geschützte" Felder zu machen.

Soweit ich weiß, ist das alles (außer Quellfilter ... pssst. Ich habe sie nicht erwähnt ...)


BEARBEITEN: Eigentlich stellt sich heraus, dass ich kann Denken Sie an eine sehr chaotische Art, geschützt zu handeln. Aber es würde wahrscheinlich bedeuten, dass alle Anrufe über das Internet geleitet werden AUTOLOAD sub. (!!)


14 für die Antwort № 3

Das funktioniert:

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

sub public_sub {
my $self = shift;

$self->$priv_func1(@_);
}

8 für die Antwort № 4

Prüfe einfach den Anrufer:

package My;

sub new {
return bless { }, shift;
}

sub private_func {
my ($s, %args) = @_;
die "Error: Private method called"
unless (caller)[0]->isa( ref($s) );

warn "OK: Private method called by " . (caller)[0];
}

sub public_func {
my ($s, %args) = @_;

$s->private_func();
}

package main;

my $obj = My->new();

# This will succeed:
$obj->public_func( );

# This will fail:
$obj->private_func( );

6 für die Antwort № 5

Was versuchst du zu machen? Vielleicht gibt es eine bessere Perl-Methode, um das zu tun, was Sie erreichen wollen.

Wenn Sie beispielsweise nicht möchten, dass sich Personen in Ihren Objekten herumärgern, weil Sie die Kapselung erzwingen möchten, können Sie so etwas wie verwenden Klasse :: InsideOut. Dieses Modul verfügt über ein Class :: InsideOut :: About-Dokumentationsmodul, das das Konzept erläutert. Es gibt auch Object :: InsideOut, die Brian Phillips bereits erwähnt hat.


3 für die Antwort № 6

Dieser OO-Stil fängt an, sich ein wenig zu fühlen"nicht perlend" nach einer Weile, wenn Sie feststellen, dass Sie nicht einfach Data :: Dumper verwenden können, um das Objekt direkt zu sichern oder in das Objekt zu schauen, um seine Daten zu überprüfen. d empfehlen die Verwendung von Object :: InsideOut. Es unterstützt private Daten und Methoden für Ihre Objekte sowie eine Reihe weiterer nützlicher Funktionen (Accessor-Generierung, Standardkonstruktor usw.).


3 für die Antwort № 7

Wir können unten in der Perl Private-Funktion etwas schreiben, um zu überprüfen, ob der Aufruf vom selben Objekt stammt wie caller[0] Paket gibt.

sub foo {
my ($s, %args) = @_;
die "Error: Private method called"
unless (caller)[0]->isa( ref($s) );
}

2 für die Antwort № 8

Wenn Sie ein System wie ElchSie können eine öffentliche / private Unterscheidung erhalten, wie gesehen Hier.


0 für die Antwort № 9

In Datei für Ihr Paket: Definieren Sie private Methoden als CODE-Ref, d. H .:

my $private_methode = sub{};