3

newメソッドにParse::RecDescentは、次のプロトタイプがあります。

sub new ($$$)
{
   # code goes here
}

そして、次のようなオブジェクトを作成すると:

my $parser = Parse::RecDescent->new($grammar);

それはパーサーを作成し、メソッドは "Parse::RecDescent" と $grammar の 2 つのパラメーターを受け取りますよね? 次のようなオブジェクトを作成しようとすると:

Parse::RecDescent::new("Parse::RecDescent",$grammar)

これは「Parse::RecDescent::new の引数が不十分です」と言って失敗しますが、このメッセージは理解できます。私は2つのパラメータのみを渡しています。ただし、矢印バージョンが機能する理由がわかりません。

説明できますか?

4

1 に答える 1

11

関数プロトタイプは、オブジェクト指向スタイルのメソッドとして呼び出すときにチェックされません。さらに、&を使用してサブを呼び出す場合は、プロトタイプのチェックをバイパスします。&sub(arg0, arg1..);

perldocからperlsub :

「&」形式は引数リストをオプションにするだけでなく、指定した引数のプロトタイプチェックも無効にします。これは、一部には歴史的な理由によるものであり、一部には自分が何をしているのかを知っている場合にチートする便利な方法があるためです。以下のプロトタイプを参照してください。

呼び出される正確なコードは継承に依存するため、呼び出される関数はコンパイル時に不確定であるため、メソッド呼び出しもプロトタイプの影響を受けません。

構文的にParse::RecDescent::new("Parse::RecDescent", $grammar)は正しいですが、これはコンストラクターを呼び出すためのかなり臭い方法です。これで、コンストラクターを(祖先ではなく)そのクラスで定義するように強制されます。引数を本当に検証する必要がある場合は、メソッド内で実行してください。

sub new
{
    my ($class, @args) = @_;
    die "Not enough arguments passed to constructor" if @args < 2;
    # ...
}

プロトタイプに関するこの以前の質問と、なぜそれらが通常それほど素晴らしいアイデアではないのかについても参照してください。

于 2010-02-12T22:19:58.183 に答える