2010-10-22 48 views
16

Tôi muốn một số thuộc tính (có lẽ đây là từ sai trong ngữ cảnh này) là riêng tư, nghĩa là chỉ sử dụng nội bộ để sử dụng đối tượng - không thể đọc hoặc ghi từ bên ngoài.Làm cách nào để tạo các biến đối tượng Moose (thuộc tính) nội bộ (riêng tư)?

Ví dụ: suy nghĩ về một số biến nội bộ đếm số lần bất kỳ tập hợp phương thức nào được gọi.

Tôi nên xác định biến số ở đâu và như thế nào?

Trả lời

13

Các Moose::Manual::Attributes cho thấy cách sau để tạo thuộc tính dành riêng:

has '_genetic_code' => (
    is  => 'ro', 
    lazy  => 1, 
    builder => '_build_genetic_code', 
    init_arg => undef, 
); 

Thiết init_arg nghĩa thuộc tính này không thể được đặt tại các nhà xây dựng. Biến nó thành rw hoặc thêm writer nếu bạn cần cập nhật.

/I3az/

+3

Câu hỏi hỏi về đọc cũng như viết. Theo như tôi có thể nói, trong phiên bản tháng 1 năm 2012 của Moose (2.0401), các thuộc tính được tạo theo cách này vẫn có thể đọc được từ bên ngoài đối tượng. Ví dụ: 'my $ m = MooseObject-> new(); in $ m -> _ genetic_code; 'sẽ in bất cứ thứ gì được lưu trong thuộc tính. Tôi không biết nếu có một cách xung quanh đó. Nó không bao giờ làm phiền tôi, nhưng tôi thấy nó đáng nói đến. –

+0

@ AlanW.Smith Sẽ thay đổi 'is => 'ro'' thành' is =>' bare'' help? Trong trường hợp đó, cách duy nhất để truy cập '_genetic_code' từ bên ngoài sẽ là nhìn trộm dưới chính Moose và nhìn vào đối tượng băm hoặc một cái gì đó, vì Moose cũng sẽ không tạo ra bộ đọc truy cập. Đúng không? – sundar

10

Bạn có thể thử một cái gì đó như thế này:

has 'call_counter' => (
    is  => 'ro', 
    writer => '_set_call_counter', 
); 

is => 'ro' làm cho các thuộc tính chỉ đọc . Moose tạo ra một getter. phương pháp của bạn sẽ sử dụng getter cho incrementing giá trị, như vậy:

sub called { 
    my $self = shift; 
    $self->_set_call_counter($self->call_counter + 1); 
    ... 
} 

writer => '_set_call_counter' tạo ra một setter tên _set_call_counter. Moose không hỗ trợ đúng thuộc tính riêng riêng. Bên ngoài mã có thể, về mặt kỹ thuật, gọi _set_call_counter. Theo quy ước, các ứng dụng không gọi phương thức bắt đầu bằng dấu gạch dưới.

+2

Bảo mật là về ẩn dữ liệu, không bảo mật dữ liệu. Perl không hỗ trợ các thuộc tính riêng tư thực sự vì bạn có thể truy cập trực tiếp các thuộc tính. Tôi chỉ muốn chỉ ra rằng nếu bạn chỉ có thể truy cập chúng gián tiếp đó sẽ là một câu chuyện khác ... – wprl

+3

* Moose * không hỗ trợ các thuộc tính riêng. Perl hoàn toàn có thể vui vẻ hỗ trợ họ bằng cách sử dụng ví dụ như một loại trường hợp đóng cửa ít hơn tự nhiên. Các hoops bạn phải nhảy qua để làm cho họ làm việc không có giá trị nỗ lực cho hầu hết các trường hợp sử dụng. Xin lỗi người đi bộ. – perigrin

2

tôi đã không thể tìm ra một cách để làm Moose thuộc tính hoàn toàn riêng tư. Bất cứ khi nào tôi sử dụng has 'name' => (...); để tạo thuộc tính, nó luôn luôn được tiếp xúc với việc đọc ở mức tối thiểu. Đối với các mục tôi muốn thực sự riêng tư, tôi đang sử dụng các biến "my" chuẩn bên trong gói Moose. Để có ví dụ nhanh, hãy lấy mô-đun sau "CountingObject.pm".

package CountingObject; 

use Moose; 

my $cntr = 0; 

sub add_one { $cntr++; } 

sub get_count { return $cntr; } 

1; 

Các tập lệnh sử dụng mô-đun đó không có quyền truy cập trực tiếp vào biến $ cntr. Họ phải sử dụng các phương thức "add_one" và "get_count" hoạt động như một giao diện cho thế giới bên ngoài. Ví dụ:

#!/usr/bin/perl 

### Call and create 
use CountingObject; 
my $co = CountingObject->new(); 

### This works: prints 0 
printf("%s\n", $co->get_count()); 

### This works to update $cntr through the method 
for (1..10) { $co->add_one(); } 

### This works: prints 10 
printf("%s\n", $co->get_count()); 

### Direct access won't work. These would fail: 
# say $cntr; 
# say $co->cntr; 

Tôi mới đến Moose, nhưng như xa như tôi có thể nói, phương pháp này cung cấp biến hoàn toàn riêng tư.

+3

Hãy coi chừng mặc dù các biến "của tôi" được chia sẻ giữa tất cả các cá thể đối tượng của bạn vì chúng là một phần của gói và không phải là một phần của hàm băm may mắn đại diện cho đối tượng. Điều này thường không phải là những gì bạn muốn. –

6

Tôi nghĩ bạn muốn MooseX::Privacy.

Các perldoc sẽ cho bạn biết tất cả các bạn nên cần - nó cho biết thêm một đặc điểm mới để các thuộc tính của bạn cho phép bạn khai báo chúng như private hay protected:

has config => (
    is  => 'rw', 
    isa => 'Some::Config', 
    traits => [qw/Private/], 
); 
3

Alan W. Smith cung cấp một biến lớp học riêng với một từ vựng biến, nhưng nó được chia sẻ bởi tất cả các đối tượng trong lớp.Hãy thử thêm một đối tượng mới đến hết đoạn mã ví dụ:

my $c1 = CountingObject->new(); 
printf("%s\n", $c1->get_count()); 
# also shows a count of 10, same as $co 

Sử dụng MooseX: Bảo mật là một câu trả lời tốt, tuy nhiên nếu bạn không thể, bạn có thể mượn một thủ thuật từ trại đối tượng bên trong-out:

package CountingObject; 

use Moose; 

my %cntr; 

sub BUILD { my $self = shift; $cntr{$self} = 0 } 

sub add_one { my $self = shift; $cntr{$self}++; } 

sub get_count { my $self = shift; return $cntr{$self}; } 

1; 

Với điều đó, bộ đếm của mỗi đối tượng được lưu trữ dưới dạng mục nhập bằng băm băm. Ở trên có thể được thực hiện một chút tersely hơn như vậy:

package CountingObject; 

use Moose; 

my %cntr; 

sub add_one { $cntr{$_[0]}++ } 

sub get_count { return $cntr{$_[0]}||0 } 

1; 
Các vấn đề liên quan