Во-первых, вы должны выяснить, что вы действительно хотите вернуть и что вы хотите, чтобы более высокий уровень мог делать с данными.
Если вы хотите вернуть копию данных или какие-либо изменения в возвращаемых данных не влияют на копию в объекте, вы не можете сделать простые решения, о которых вам говорят другие ответы, потому что они возвращают мелкие копии , которые все еще будут делиться внутренними ссылками. Вам нужно сделать глубокую копию , а затем вернуть отключенную структуру данных. Storable делает это легко с dclone
:
use Storable qw( dclone );
sub some_method {
my( $self, ... ) = @_;
...;
my $clone = dclone( $self->{_runs} );
$clone;
}
Если вы хотите, чтобы более высокий уровень изменил объект путем изменения возвращенной структуры данных, просто верните ссылку, которую вы уже сохранили. Вам не нужно ничего делать для этого:
sub some_method {
my( $self, ... ) = @_;
...;
$self->{_runs};
}
Кроме того, ваша задача - создать интерфейс, чтобы людям не приходилось думать о вашей структуре данных на более высоком уровне. Вы инкапсулируете все, чтобы детали реализации не показывались. Таким образом, вы можете изменить реализацию, не нарушая код более высокого уровня (если интерфейс стабилен).
Вы создаете метод runs
, который возвращает список прогонов:
sub get_run_keys {
my( $self ) = @_;
keys %{ $self->{_runs} };
}
Или, может быть, вы просто хотите значения:
sub get_run_values {
my( $self ) = @_;
values %{ $self->{_runs} };
}
Или, может быть, все это:
sub get_run_hash {
my( $self ) = @_;
$self->{_runs}; # subject to the cloning stuff I mentioned earlier
}
Когда вы хотите получить значения для определенного прогона, вы получаете к нему доступ другим способом:
sub get_run {
my( $self, $key ) = @_;
$self->{_runs}{$key};
}
Установка значения прогона аналогична:
sub set_run {
my( $self, $key, $value ) = @_;
$self->{_runs}{$key} = $value;
}
Теперь ваш более высокий уровень ничего не знает об инфраструктуре, а имена методов описывают то, что вы пытаетесь сделать вместо того, как инфраструктура должна это делать:
foreach my $key ( $self->get_run_keys ) {
my $run = $self->get_run( $key );
...;
$self->set_run( $key, $new_value );
}
Объектно-ориентированный дизайн - большая тема, и вы можете многое сделать. Этого достаточно, чтобы начать. Вы также можете перенести другие операции:
sub does_run_exist {
my( $self, $key ) = @_;
exists $self->{_runs}{$key};
}
sub delete_runs {
my( $self, @keys ) = @_;
delete $self->{_runs}{$key} foreach my $keys ( @keys );
}
sub reset_runs {
my( $self, $key ) = @_;
$self->{_runs} = {};
}