5

私はネクタイについて学び始めたばかりです。次のことをしたい 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;

実行すると、スクリプトは次のエラーで終了し ます

そのメッセージを正しく理解すれば$var->print_method、メソッドprint_methodが呼び出される文字列に解決されます。どのようにネクタイの恩恵を受けることができますか?また、変数をオブジェクトとして使用することもできますか?

編集:少し実験した後、フェッチで $self を返すと、メソッドを呼び出すことができますが、フェッチはアドレスを返さないことがわかりました。

編集 2: perl 僧侶が解決策を提供してくれました:結ばれました。tie はオブジェクト VARIABLE への参照を返します。

自分のメソッドと結びつけることで、やりたいことはすべて成し遂げることができます。

4

2 に答える 2

10

ネクタイはこの仕事には不適切な道具です。通常のデータ型と同じインターフェイスが必要であるが、操作の動作方法をカスタマイズしたい場合は、tie を使用します。スカラーがすでに行っているように、文字列にアクセスして格納したいので、tie は何もしません。

URIモジュールまたはそのサブクラス、そしておそらくいくつかのオーバーロードが必要なようです。

本当にこれを行う必要がある場合は、正しい変数を使用する必要があります。タイは、指定した変数を指定したクラスに接続しますが、それはまだ通常のスカラーです (参照ではありません)。メソッドを呼び出したい場合は、返されるオブジェクトを使用する必要があります。

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

関連付けられたスカラーしかない場合は、シークレット オブジェクトを取得することもできます。

my $secret_object = tied $normal_scalar;

Mastering Perlには、tie に関する章全体があります。

于 2009-02-07T21:32:14.040 に答える
9

通常の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オブジェクトの方がおそらく良いでしょう。

于 2009-02-07T19:49:58.380 に答える