Документация
HTML CSS PHP PERL другое

Section 15.14.  Operator Overloading

 
Previous
Table of Contents
Next

15.14. Operator Overloading

Overload only the isomorphic operators of algebraic classes.

Operator overloading is very tempting. It offers the prospect of being able to express operations of your new data type in a compact and syntactically distinctive way. Unfortunately, overloading operators more often produces code that is both hard to comprehend and vastly less maintainable. For example:

    
    # Special string class with useful operators...
    package OpString;
    {
        use overload (
            '+'   => 'concatenate',
            '-'   => 'up_to',
            '/'   => 'either_or',
            '<=>' => 'swap_with',
            '~'   => 'optional',

            # Use Perl standard behaviours for other operations...
            fallback => 1,
        );
    }

    # And later...

    $search_for = $MR/$MRS + ~$first_name + $family_name;

    $allowed_pet_range = $CAT-$DOG;

    $home_phone <=> $work_phone;

Though the resulting client code is compact, the non-standard usages of the various operators make it much harder to understand and maintain, compared to:


    package OpString;
    {
        use overload (
            '.'   => 'concatenate',

            
# Use Perl standard behaviours for other operations...
fallback => 1, ); }
# And later...
$search_for = $MR->either_or($MRS) . first_name->optional( ) . $family_name; $allowed_pet_range = $CAT->up_to($DOG); $home_phone->swap_with($work_phone);

Note that overloading the "dot" operator was perfectly acceptable here, as it (presumably) works just like Perl's built-in string concatenator.

Overloading other operators can make good sense (and good code), provided two conditions are met. First, the operators you choose to overload must match the standard algebraic notation within the problem's native domain: the set of operators that the domain experts routinely use. Second, the standard domain-specific notation you're recreating in your Perl class must conform to the Perlish precedences and associativities of the operators you're overloading.

Together, those two conditions ensure that the appearance of the selected Perl operator mirrors that of the desired problem domain operator, and that the algebraic properties (precedence and associativity) of the problem domain operator mirror those of the selected Perl operator. In other words, there must be a one-to-one correspondence of form and function: the two notations must be isomorphic.

For example, if your domain experts use the operators +, ., and ! on certain types of values, then it may be appropriate to overload those Perl operators for the corresponding class. However, if those domain experts treat . as being of higher precedence than + (as many mathematicians do), then overloading the corresponding Perl operators isn't appropriate, because . and + have the same precedence in Perl. That kind of mismatch between expectation and reality always leads to hard-to-find bugs.

On the other hand, if the domain experts use ±, ·, and ¬, it's definitely inappropriate to overload the Perl operators +, ., and ! to represent them. The notation isn't the same, so it won't help those who understand the domain to understand your code. In fact, the mismatch of algebraic syntax is far more likely to get in the way.

    Previous
    Table of Contents
    Next
    © 2000- NIV