在Perl中如何判断一个对象是否实现了某个方法?

6

我有一个包含多态对象的数组,这些对象实现了两个(非正式的)接口。我希望能够通过反射来区分它们,例如:

if (hasattr(obj, 'some_method')) {
    # `some_method` is only implemented by one interface.
    # Now I can use the appropriate dispatch semantics.
} else {
    # This must be the other interface.
    # Use the alternative dispatch semantics.
}

也许像这样的东西可以工作吗?
if (*ref(obj)::'some_method') {
    # ...

我很难分辨语法何时尝试调用子例程以及何时返回子例程引用。我对软件包符号表不太熟悉,只是试图进行一些简单的操作。:-)
提前感谢!
1个回答

16
use Scalar::Util qw(blessed);
if( blessed($obj) and $obj->can('some_method') ){ 

}

"can" 在这里是所有类从UNIVERSAL继承的一个方法。类可以重写此方法,但这并不是一个好主意。

此外,“can”返回对函数的引用,因此您可以执行:

$foo->can('some_method')->( $foo , @args );
或者
my $sub = $foo->can('some_method'); 
$foo->$sub( @args ); 

编辑更新了链式语法,感谢Brian Phillips。


“can” 是一种保留的方法名称吗?还是说如果您使用它,就会不小心自己搬起石头砸自己的脚? - cdleary
不要忘记你需要明确地将对象传递给由can返回的函数引用:$foo->can('some_method')->($foo, @args)。另外,也可以这样写:my $sub = $foo->can('some_method'); $foo->$sub(@args); - Brian Phillips
一般禁止覆盖 can 的命令有点过于严格。这样做有很好而且重要的原因。 - darch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接