2017-08-28 107 views
4

我即将完成学习Intermediate Perl书。SUPER :: methods在Perl中测试分支分配

在第18章对象销毁介绍以下DESTROY方法定义:

# lib/Animal.pm 
package Animal { 
    # ... 
    sub DESTROY { 
    my $self = shift; 
    if ($self->{temp_filename}){ 
     my $fh = $self->{temp_fh}; 
     close $fh; 
     unlink $self->{temp_filename}; 
    } 
    print '[', $self->name, " has died.]\n"; 
    } 
# ... 
} 

# lib/Horse.pm 
package Horse { 
    use parent qw(Animal) 
    # ... 
    sub DESTROY { 
    my $self = shift; 
    $self->SUPER::DESTROY if $self->can('SUPER::DESTROY'); 
    print "[", $self->name, " has gone off to the glue factory.]\n"; 
    } 
# ... 
} 

几个后不成功的尝试,我写了基于this answer这个测试:

# t/Horse.t 
#!perl -T 

use strict; 
use warnings; 
use Test::More tests => 6; 
use Test::Output; 
# some other tests 

# test DESTROY() when SUPER::DESTROY is not defined; 
{ 
    my $tv_horse = Horse->named('Mr. Ed'); 
    stdout_is(sub { $tv_horse->DESTROY }, "[Mr. Ed has died.]\n[Mr. Ed has gone off to the glue factory.]\n", 
     'Horse DESTROY() when SUPER::DESTROY is defined'); 
} 

{ 
    my $tv_horse = Horse->named('Mr. Ed'); 
    sub Animal::DESTROY { undef } 
    stdout_is(sub { $tv_horse->DESTROY }, "[Mr. Ed has gone off to the glue factory.]\n", 
     'Horse DESTROY() when SUPER::DESTROY is not defined'); 
} 

我无法测试由于方法重定义sub Animal::DESTROY { undef }也影响前一个程序段中的测试,所以两种情况下的输出均正确。

您是否知道确保方法重新定义按预期工作的方法?

感谢

+2

如果你正在写的'Animal'类和'Animal'总是与'马一起使用',那么你知道'Animal'提供了DESTROY方法 - ' - > can('SUPER :: DESTROY')检查变得有点不必要。我只是直接调用'$ self-> SUPER :: DESTROY'。 – amon

+3

Btw不要通过直接调用它来触发DESTROY方法,这可能会多次调用DESTROY。相反,'undef $ tv_horse'清除将触发析构函数的变量。 – amon

+0

好的,谢谢你的建议 – mabe02

回答

6

这应该设置移除/重新定义子程序只有等到封闭块结束,

{ 
    # not needed when removing method 
    # no warnings 'redefine'; 

    my $tv_horse = Horse->named('Mr. Ed'); 
    # returns undef 
    # local *Animal::DESTROY = sub { undef }; 

    # remove the mothod until end of the enclosing block 
    local *Animal::DESTROY; 

    # .. 
} 
+0

感谢您的快速回复。此解决方案正在运行!但是'Devel :: Cover'并没有检测到这个分支案例: blib/lib/Horse.pm line | %|覆盖范围|分支 14 | 50 | T(绿色)| F(红色)|如果$ self-> can('SUPER :: DESTROY') – mabe02

+0

你想要'DESTROY'返回'undef',还是一起删除'DESTROY'? –

+2

@ mabe02要完全删除该方法,只需要定位glob而不指定一个新的sub:'local * Animal :: DESTROY;'就足够了。 – amon