UNIVERSAL と Scalar::Util::blessed の話

毎度和訳お疲れ様です>hio-san

逆にいまいちわかんないのが UNIVERSAL まわり。isa類を関数として使うのはよろしくないで, メソッドとして使ってね&blessされているかも確認したかったら Scalar::Utilblessed (オブジェクトの時)か reftype (なにかHASHとかそんな時)をあわせてよろしくらし。blessed($obj) && $obj->isa('CLASS')reftype($hash) eq 'HASH' みたいな?

perl-5.10.0 Released - ひおにっき(2007-12-19)

前半の「関数として使わずにメソッドとして使ってね」という話は UNIVERSAL::isa($hoge, 'Huga') を使うべきではない - daily dayflower の話だと思います。

後者の「bless されているかも確認したかったら」というのは,

If you want to be sure that you're calling isa as a method, not a class, check the invocant with blessed from Scalar::Util first:

UNIVERSAL - 全てのクラス(ブレスされたリファレンス)の基底クラス

のところだと思うんですけど,これはたとえば $obj という変数に,インスタンスではなくてクラス名が入ってしまった場合にも isa が TRUE になってしまうと困るケースについて書いているんだと思います。

拙い例ですが,

#!/usr/bin/perl
# - universal.pl

package ClassA;
use base qw( Class::Accessor );

package ClassB;
use base qw( ClassA );

package main;

use Scalar::Util qw( blessed );

my $o = ClassB->new();
my $n = 'ClassB';

warn 'obj true' if $o->isa('ClassA');
warn 'VAL true' if $n->isa('ClassA');

warn 'VAL(as obj) true'  if   (blessed $o && $o->isa('ClassA'));
warn 'VAL(as obj) false' if ! (blessed $n && $n->isa('ClassA'));

みたいなコードを想像していただくと((ほんとは eval で囲うべきですが))。

obj true at universal.pl line 17.
VAL true at universal.pl line 18.
VAL(as obj) true at universal.pl line 20.
VAL(as obj) false at universal.pl line 21.

両者ともに 5.10 だからどう,という話ではないですけど。


ちなみに Scalar::Util::reftype ですが,HASH ってクラス名をつけるという乱暴なことしないのなら ref でいいんじゃないのとか個人的に思うんですが,なにか所以があるのですかね。