実行時にPerlシンボルテーブルからメソッドを削除する必要があります。を使用してこれを実行しようとしましundef &Square::area
たが、関数は削除されますが、いくつかの痕跡が残ります。具体的には、$square->area()
が呼び出されると、Perlは、私が期待している「未定義のサブルーチン&Square :: area called」ではなく、「CODE参照ではない」と文句を言います。
「なぜそれが重要なのですか?関数を削除したのに、なぜそれを呼び出すのですか?」と尋ねるかもしれません。答えは、私がそれを呼んでいないということです、Perlはそうです。SquareはRectangleから継承し、継承チェーンをに渡したいのですが、メソッドが存在しないSquareをスキップしてRectangleのarea()にフォール$square->area
スルー&Rectangle::area
する代わりに、メソッド呼び出しは「コード参照ではありません」で終了します。
奇妙なことに、これは&Square :: areaがtypeglob割り当てによって定義された場合にのみ発生するようです(例*area = sub {...}
)。関数が標準的なsub area {}
アプローチを使用して定義されている場合、コードは期待どおりに機能します。
また興味深いことに、グロブ全体の定義を解除すると、期待どおりに機能します。サブルーチン自体の定義を解除しないでください。
症状を説明し、正しい動作と対比する短い例を次に示します。
#!/usr/bin/env perl
use strict;
use warnings;
# This generates "Not a CODE reference". Why?
sub howdy; *howdy = sub { "Howdy!\n" };
undef &howdy;
eval { howdy };
print $@;
# Undefined subroutine &main::hi called (as expected)
sub hi { "Hi!\n" }
undef &hi;
eval { hi };
print $@;
# Undefined subroutine &main::hello called (as expected)
sub hello; *hello = sub { "Hello!\n" };
undef *hello;
eval { hello };
print $@;
更新:それ以来、Package :: Stashを使用してこの問題を解決しました(@Etherに感謝)が、そもそもなぜそれが起こっているのかまだ混乱しています。perldoc perlmod
言う:
package main;
sub Some_package::foo { ... } # &foo defined in Some_package
これは、コンパイル時のtypeglob割り当ての省略形です。
BEGIN { *Some_package::foo = sub { ... } }
しかし、関数の定義を解除した後、2つは異なる動作を引き起こすため、これは単なる速記ではないようです。これが(1)誤ったドキュメント、(2)perlのバグ、または(3)PEBCAKのいずれの場合であるかを誰かに教えてもらえれば幸いです。