2017-07-24 2 views
4

Als mentioned earlier today versuche ich Attribute zu einer Instanz zu setzen, wenn eine ihrer Methoden aufgerufen wird. Ich möchte dieses Attribut auch privat machen. Wie bereits erwähnt, kann ich dieses Attribut nicht auf ro setzen, da dies auch den Lesezugriff innerhalb der Klasse verbietet. Deshalb setze ich es jetzt auf rw, aber ich habe begonnen, das MooseX::Privacy Modul zu verwenden. Meine Attributdeklaration sieht somit wie folgt:Die Verwendung von Moose zum Ändern der Methodenargumente kollidiert mit Datenschutz

has 'grow_params' => (
    is => 'rw', 
    isa => 'HashRef', 
    traits => [qw/Private/], 
); 

Dies funktioniert gut, wenn ich einfach etwas tun:

sub grow { 
    my ($self, $params) = @_; 
    $self->grow_params($params); 
} 

Ich möchte jedoch einige Parameter Kontrollen zu tun. Nach dem Lesen der Dokumentation scheint es, dass der beste Ort dafür before ist. Wenn ich das versuche, stoße ich auf Probleme.

Zum Beispiel mit before:

before 'grow_params' => sub { 
    my ($self, $params) = @_; 
    # Setting default value 
    $params->{'overripe'} = exists $params->{'overripe'} ? $params->{'overripe'} : 0; 
    # Making sure its boolean 
    confess "Argument 'overripe' has to be 0 or 1" 
    unless ($params->{'overripe'} == 0 || $params->{'overripe'} == 1); 
}; 

Dies führt zu dem folgenden Fehler:

Attribute grow_params is private at C:/strawberry/perl/site/lib/MooseX/Privacy/Meta/Attribute/Private.pm line 13. 

(ich habe auch versucht, das Attribut Protected Einstellung, zu raten, dass vielleicht eine Unterklasse erstellt wurde, aber vergebens.) Das Attribut ist zwar privat, aber ich versuche, es innerhalb der Klasse zu ändern, oder? Die Ablaufverfolgung sieht so aus, also würde ich annehmen, dass die tatsächliche Einstellung von Banana versucht wird, oder fehle ich etwas?

Attribute grow_params is private at c:/strawberry/perl/site/lib/MooseX/Privacy/Meta/Attribute/Private.pm line 13. 
     MooseX::Privacy::Meta::Attribute::Private::_check_private(Moose::Meta::Class::__ANON__::SERIAL::9=HASH(0x3fd4a00), "Class::MOP::Method::Wrapped", "grow_params", "Banana", "Banana") called at c:/strawberry/perl/site/lib/MooseX/Privacy/Meta/Attribute/Privacy.pm line 31 
     Banana::grow_params(Banana=HASH(0x25223e8), HASH(0xed97a8)) called at c:/strawberry/perl/site/lib/Class/MOP/Method/Wrapped.pm line 44 
     Banana::_wrapped_grow_params(Banana=HASH(0x25223e8), HASH(0xed97a8)) called at c:/strawberry/perl/site/lib/Class/MOP/Method/Wrapped.pm line 95 
     Banana::grow_params(Banana=HASH(0x25223e8), HASH(0xed97a8)) called at C:\xampp\htdocs\grinding\banana\/Banana.pm line 31 
     Banana::grow(Banana=HASH(0x25223e8), HASH(0xed97a8)) called at run.pl line 16 

Der vollständige Code, um selbst zu laufen.

# Banana.pm 
package Banana; 

use strict; 
use warnings; 
use Carp qw(confess); 

use Moose; 
use MooseX::Privacy; 

has ['peel', 'edible'] => (
    is => 'ro', 
    isa => 'Bool', 
    required => 1, 
); 

has 'color' => (
    is => 'ro', 
    isa => 'Str', 
    required => 1, 
); 

has 'grow_params' => (
    is => 'rw', 
    isa => 'HashRef', 
    traits => [qw/Private/], 
); 

sub grow { 
    my ($self, $params) = @_; 
    $self->grow_params($params); 
} 

before 'grow_params' => sub { 
    my ($self, $params) = @_; 
    # Setting default value 
    $params->{'overripe'} = exists $params->{'overripe'} ? $params->{'overripe'} : 0; 
    # Making sure its boolean 
    confess "Argument 'overripe' has to be 0 or 1" 
    unless ($params->{'overripe'} == 0 || $params->{'overripe'} == 1); 
}; 

1; 

# run.pl 
use strict; 
use warnings; 

use File::Basename qw(fileparse dirname); 
use Cwd qw(abs_path); 

# Add current directory to @INC 
use lib (fileparse(abs_path($0)))[1]; 

use Banana; 

my $chiquita = Banana->new({ 
    peel => 1, 
    edible => 0, 
    color => 'green' 
}); 

$chiquita->grow({ 
    size => 'medium', 
    color => 'yellow' 
}); 

Antwort

3

Wenn wir uns in die Umsetzung von MooseX::Privacy, mehr speziell in MooseX::Privacy::Meta::Attribute::Private v0.05, können wir sehen, was passiert.

sub _check_private { 
    my ($meta, $caller, $attr_name, $package_name) = @_; 
    confess "Attribute " . $attr_name . " is private" 
     unless $caller eq $package_name; 
} 

So muss es sein, dass $caller zu $package_name nicht gleich ist. Was ist eine Möglichkeit, den Begriff der Privatsphäre in Perl ausgedrückt, denke ich.

Wer ist der Aufrufer einer before Methode? I leicht vor der Überprüfung den Code geändert, $caller zu drucken. Hier sind die Täter:

Class::MOP::Method::Wrapped

, die mit dem zu tun hat, wie Verfahren Modifikatoren umgesetzt werden (wie der Name schon sagt).

So wie ich es sehe, sind Ihre Erwartungen vernünftig und dies ist ein Defekt in MooseX::Privacy und die Art und Weise es befasst sich mit dem Innenleben des Ökosystems MOP.

+0

Gut finden, danke! Ich habe einen Fehlerbericht an cpan geschickt, aber da der letzte Fehler (vor 11 Monaten) nicht beantwortet wurde, schätze ich nicht viel Hoffnung. –

Verwandte Themen