Pergunta

Eu apenas comecei a aprender sobre laço . Eu tenho uma classe chamada Fazer a ligação que eu gostaria de fazer o seguinte:

  • se buscado, retornar o endereço do link
  • se armazenado, armazenar o novo endereço
  • ser capaz de chamar métodos nele

Até agora, o meu código é:


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;

E o código que estou usando para verificar a funcionalidade é:


use Link;

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

Quando correu, o script terminará com o seguinte erro: Não é possível chamar o método "print_method" sem um pacote ou referência de objeto no tietest.pl linha 4. .

Se eu entendo a sua mensagem corretamente, $var->print_method resolve alguma corda sobre a qual o método print_method é chamado. Como eu poderia beneficiar de empate, mas também usar a variável como um objeto?

EDIT: depois de experimentar um pouco, eu descobri que se eu voltar $ self em buscar, eu posso chamar os métodos, no entanto, buscar não retornará o endereço

.

EDIT 2: os monges Perl fornecido me a solução: amarrado . amarrado irá retornar uma referência para o objeto variável.

Ao combinar amarrado com meus métodos, eu posso realizar tudo o que eu queria.

Foi útil?

Solução

Tie é a ferramenta errada para este trabalho. Você usa laços quando você quer a mesma interface como tipos de dados normais, mas quero personalizar a forma como as operações de fazer o seu trabalho. Desde que você deseja acessar e armazenar uma string como um escalar já faz, empate não faz nada para você.

Parece que você deseja que o URI módulo, ou uma subclasse do mesmo, e talvez alguma sobrecarga.

Se você realmente precisar fazer isso, você precisa usar a variável direita. A amarrar conecta-se a variável que você especificar para a classe que você especificar, mas ainda de um escalar normal (e não uma referência). Você tem que usar o objeto que ele retorna, se você quiser chamar métodos:

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

Você também pode obter o objeto segredo se você só tem a escalar amarrado:

my $secret_object = tied $normal_scalar;

Eu tenho um capítulo inteiro sobre empate na Mastering Perl .

Outras dicas

Sugiro fazer um objeto normal de Perl e depois sobrecarga ing stringification. Você perde a capacidade de armazenar um valor através da atribuição, mas mantêm a capacidade de obter o valor pelo impressão do objeto. Uma vez que você começar a querer chamar métodos diretamente, um objeto é provavelmente o que você quer.

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;

Exemplo de utilização:

use Link;

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

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

Se você realmente quer atribuição ao trabalho também, você pode combinar um objeto normal com stringification sobrecarregado (Link, acima) com 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;

Exemplo de utilização:

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

Isso tudo é bastante hediondo e um longo caminho a percorrer apenas para obter a capacidade duvidosa para atribuir a algo que você também pode chamar métodos e também imprimir como está. Um objeto URI padrão com stringification é provavelmente a melhor aposta.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top