Как я могу вызывать методы для связанной переменной?

StackOverflow https://stackoverflow.com/questions/524308

  •  22-08-2019
  •  | 
  •  

Вопрос

Я только начал узнавать о галстук.У меня есть класс с именем Link, в котором я хотел бы сделать следующее:

  • если извлечено, верните адрес ссылки
  • если сохранено, сохраните новый адрес
  • иметь возможность вызывать на нем методы

Пока что мой код таков :


package Link;

sub FETCH {
    my $this = shift;
    return $this->{"site"};
}

sub STORE {
    my ($self,$site) = @_;
    $self->{"site"}   = $site;
}

sub print_method {
    my $self = shift;
    print $self->{"site"};
}

sub TIESCALAR {
    my $class = shift;
    my $link  = shift;
    my $this  = {};
    bless($this,$class);
    $this->{"site"} = $link;
    return $this;
}

1;

И код, который я использую для проверки функциональности, является:


use Link;

tie my $var,"Link","http://somesite.com";
$var->print_method;

При запуске скрипт завершится со следующей ошибкой:Не удается вызвать метод "print_method" без ссылки на пакет или объект в tietest.pl строка 4..

Если я правильно понимаю его сообщение, $var->print_method преобразуется в некоторую строку, для которой метод print_method называется.Как я мог бы извлечь выгоду из tie, но также использовать переменную в качестве объекта?

Редактировать:немного поэкспериментировав, я обнаружил, что если я верну $self при выборке , я могу вызвать методы , однако выборка не вернет адрес .

ПРАВКА 2: монахи perl предоставили мне решение : связанный .привязанный вернет ссылку на объектную ПЕРЕМЕННУЮ .

Комбинируя tied с моими методами , я могу достичь всего , чего хотел .

Это было полезно?

Решение

Галстук - неподходящий инструмент для этой работы.Вы используете ties, когда хотите иметь тот же интерфейс, что и обычные типы данных, но хотите настроить способ выполнения операций.Поскольку вы хотите получить доступ к строке и сохранить ее точно так же, как это уже делает скаляр, tie ничего не делает для вас.

Похоже, ты хочешь, чтобы URI ( УРИ ) модуль или его подкласс, и, возможно, некоторая перегрузка.

Если вам действительно нужно это сделать, вам нужно использовать правильную переменную.В галстук подключает указанную вами переменную к указанному вами классу, но это все еще обычный скаляр (а не ссылка).Вы должны использовать объект, который он возвращает, если вы хотите вызвать методы:

my $secret_object = tie my($normal_scalar), 'Tie::Class', @args;
$secret_object->print_method;

Вы также можете получить секретный объект, если у вас есть только привязанный скаляр:

my $secret_object = tied $normal_scalar;

У меня есть целая глава о привязке Освоение Perl.

Другие советы

Я предлагаю создать обычный объект Perl, а затем перегрузкаредактирование строки.Вы теряете возможность сохранять значение посредством присваивания, но сохраняете возможность извлекать значение путем печати объекта.Как только вы начинаете хотеть вызывать методы напрямую, объект, вероятно, является тем, что вам нужно.

package Link;

use strict;
use Carp;

use overload
(
  '""'      => sub { shift->site },
   fallback => 1,
);

sub new 
{
  my $class = shift;

  my $self = bless {}, $class;

  if(@_)
  {
    if(@_ == 1)
    {
      $self->{'site'} = shift;
    }
    else { croak "$class->new() expects a single URL argument" }
  }

  return $self;
}

sub site
{
  my $self = shift;
  $self->{'site'} = shift  if(@_);
  return $self->{'site'};
}

sub print_method
{
  my $self = shift;
  print $self->site, "\n";
}

1;

Пример использования:

use Link;

my $link = Link->new('http://somesite.com');

print $link, "\n";   # http://somesite.com
$link->print_method; # http://somesite.com

Если вы действительно хотите, чтобы присваивание тоже работало, вы можете объединить обычный объект с перегруженной строкой (Link, выше) с tie:

package LinkTie;

use strict;
use Link;

sub FETCH
{
  my $this = shift;
  return $this->{'link'};
}

sub STORE
{
  my($self, $site) = @_;
  $self->{'link'}->site($site);
  return $site;
}

# XXX: You could generalize this delegation with Class::Delegation or similar
sub print_method
{
  my $self = shift;
  print $self->{'link'}->print_method;
}

sub TIESCALAR
{
  my $class = shift;
  my $self = bless {}, $class;
  $self->{'link'} = Link->new(@_);
  return $self;
}

1;

Пример использования:

tie my $link,'LinkTie','http://somesite.com';
print $link, "\n";   # http://somesite.com
$link->print_method; # http://somesite.com

$link = 'http://othersite.com';

print $link, "\n";   # http://othersite.com
$link->print_method; # http://othersite.com

Все это довольно отвратительно, и предстоит пройти долгий путь только для того, чтобы получить сомнительную возможность присваивать чему-то, для чего вы также можете вызывать методы, а также печатать как есть.Стандартный объект URI со строковой обработкой, вероятно, является лучшим выбором.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top