有没有一个好的Perl Handlers介绍?

3
我正在使用Perl模块XML::SemanticDiff来比较两个XML文档。我想编写自己的自定义处理程序,但是由于我相对较新于Perl,所以不知道如何实现。
我了解处理程序只是在发生某些事件时调用的子例程。但是我对这些事件如何调用我的代码中的方法的实现细节感到困惑。
例如,该模块的基本实现始于以下内容:
my $diff = XML::SemanticDiff->new(keepdata=> 1, keeplinenums => 1, diffhandler => 1);
my @changes = $diff->compare($file1, $file2);

我知道我的自定义处理程序大致会是这样的:

sub element_value($self, $element, $to_element_properties, $fromdoc_element_properties) {
  my ($self, @args) = @_;

}

但是是否需要介入代码来实际调用这个子程序?例如:
foreach my $change (@changes) {
  $change->element_value(some_arguements_here);
}

当执行$diff->compare($file1, $file2);时,处理程序自动调用吗?任何指针将不胜感激。
1个回答

2

是的,它们由引擎“自动幻术”调用。

如果您查看源代码(链接到库的 CPAN 页面 XML::SemanticDiff),您可以轻松地看到它是如何完成的:

sub compare {
    # ... some code

       # element value test
        unless ($from_doc->{$element}->{TextChecksum} 
             eq $to_doc->{$element}->{TextChecksum}) {
            push (@warnings, $handler->element_value($element, 
                                                     $to_doc->{$element}, 
                                                     $from_doc->{$element}))
                      if $handler->can('element_value');
        }

有三种类型的处理程序子例程(取决于使用它们的库的设计):

  1. Predefined name. Meaning, the library is designed to allways call a sub with a fixed name called "XYZ()" in a particular scenario. This is very tricky to get right in terms of "which namespace is searched for the sub with that name"? To address that problem, a more common approach is #2:

  2. A custom diff-handler class with predefined method names. As you can see from XML::SemanticDiff documentation, this is the case with your library.

    The class is often inheriting from some existing base handler class with default handlers that should be overritten by your custom subclass. Alternately, it merely needs to implement some/all predefined methods but doesn't have to inherit (the latter is the case here).

    In case of XML::SemanticDiff, you tell the module what your custom handler is by giving it an object of the custom handler class:

    use XML::SemanticDiff;
    use MyCustomHandlerModule;
    my $handlerObj = MyCustomHandlerModule->new();
    my $diff = XML::SemanticDiff->new({ diffhandler => $handlerObj });
    
  3. Registered handlers. Most often, the registration is handled via passing a subroutine reference:

    sub myHandler1 { ... };
    sub myHandler2 { ... };
    my $obj = My::Library->new({ Event1_handler => &myHandler1
                               , Event2_handler => &myHandler2 })
    

    This second method is more flexible and is significantly more frequently used.


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