首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么我不能使用UNIVERSAL::isa呢?

为什么我不能使用UNIVERSAL::isa呢?
EN

Stack Overflow用户
提问于 2008-10-15 10:57:47
回答 5查看 6.6K关注 0票数 17

根据这个

http://perldoc.perl.org/UNIVERSAL.html

我不应该使用UNIVERSAL::isa(),而应该使用$obj->isa()或CLASS->isa()。

这意味着首先要找出某个东西是否是引用,然后是对这个类的引用,我必须这样做

eval { $poss->isa("Class") }

检查一下$@和所有的口香糖,否则

use Scalar::Util 'blessed';
blessed $ref && $ref->isa($class);

我的问题是为什么?UNIVERSAL::isa这样调用有什么问题吗?对于像这样的东西,它要干净得多:

my $self = shift if UNIVERSAL::isa($_[0], __PACKAGE__)

查看是否正在对象上调用此函数。有没有一个很好的干净的替代方案,不会因为和号和潜在的长行而变得繁琐?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2008-10-15 11:18:49

主要问题是,如果直接调用UNIVERSAL::isa,就会绕过任何重载了isa的类。如果这些类依赖于重载行为(它们可能会这样做,否则就不会覆盖它),那么这就是一个问题。如果您直接在受保护的对象上调用isa,那么在任何一种情况下都将调用正确的isa方法(如果存在,则重载;如果不存在,则调用UNIVERSAL::)。

第二个问题是,就像isa的其他用法一样,UNIVERSAL::isa只会在有福的引用上执行您想要的测试。它对非祝福引用和简单标量有不同的行为。所以你不检查$ref是否有福的例子是不正确的,你忽略了一个错误条件,并使用了UNIVERSAL的替代行为。在某些情况下,这可能会导致细微的错误(例如,如果你的变量包含一个类名)。

考虑一下:

use CGI;

my $a = CGI->new();

my $b = "CGI";

print UNIVERSAL::isa($a,"CGI");  # prints 1, $a is a CGI object.
print UNIVERSAL::isa($b,"CGI");  # Also prints 1!! Uh-oh!!

所以,总之,不要使用UNIVERSAL::isa...执行额外的错误检查,并直接在对象上调用isa

票数 33
EN

Stack Overflow用户

发布于 2008-10-15 11:14:30

请参阅UNIVERSAL::isaUNIVERSAL::can的文档,了解为什么不应该这样做。

简而言之,有一些重要的模块确实需要覆盖'isa‘(比如Test::MockObject),如果你把它作为一个函数调用,你就破坏了这一点。

我不得不说,my $self = shift if UNIVERSAL::isa($_[0], __PACKAGE__)在我看来并不是很干净--反Perl的倡导者会抱怨线路噪音。:)

票数 9
EN

Stack Overflow用户

发布于 2008-10-15 11:13:21

为了直接回答您的问题,答案位于您链接到的页面的底部,即如果包定义了isa方法,则直接调用UNIVERSAL::isa不会调用包的isa方法。从面向对象的角度来看,这是非常不直观的行为。

这篇文章的其余部分只是关于你为什么要这样做的更多问题。

在类似上面的代码中,在什么情况下特定的isa测试会失败?也就是说,如果它是一个方法,在哪种情况下,第一个参数不会是package类或它的实例?

我之所以这样问,是因为我想知道是否有合法的理由,让你一开始就想测试第一个参数是不是对象。也就是说,你只是想抓住人们说FooBar::method而不是FooBar->method$foobar->method吗?我猜Perl不是为这种纵容而设计的,如果人们错误地使用了FooBar::method,他们很快就会发现的。

您的里程可能会有所不同。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/204316

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档