Tilly's meditation about breaking can made me think when I use can in my code. Here's my, rather short, list.

Abigail

Replies are listed 'Best First'.
Re: When I use "can"
by eserte (Deacon) on Apr 06, 2004 at 16:45 UTC
    The obvious usage: feature testing. For example, if a Tk component uses an Entry widget and optionally (if installed) a HistEntry widget, then adding to the entry's history would be done with:
    if ($entry->can("historyAdd")) { $entry->historyAdd(...); }
    Similar if a module adds a feature (speak: method) in a later version, but you don't know when exactly and won't hardcode the module's version in your code.
Re: When I use "can"
by liz (Monsignor) on Apr 07, 2004 at 11:45 UTC
    Do you really need to check whether import exists?
    Module -> import (args...) if Module -> can ("import");
    Hmmm... This doesn't create any errors:
    $perl -e 'Foo->import' $
    whereas this does generate an error:
    $ perl -e 'Foo->bar' Can't locate object method "bar" via package "Foo" (perhaps you forgot + to load "Foo"?) at -e line 1. $
    This implies to me that you can call the import method without having to worry whether it exists or not. perlfunc states with use:
    If no "import" method can be found then the call is skipped.
    
    That can construed as to only applying to use, so maybe the wording of the documentation should be changed.

    Liz

      If no "import" method can be found then the call is skipped.

      That can construed as to only applying to use, so maybe the wording of the documentation should be changed.

      It's documented in perlsub/Autoloading:
      (As an exception, a method call to a nonexistent "import" or "unimport" method is just skipped instead.)
      (The unimport case is new as of 5.6.1.)
Re: When I use "can"
by dws (Chancellor) on Apr 06, 2004 at 19:46 UTC

    Here's my, rather short, list.

    I'll occassionally use can in a unit test, to verify that an object implements an interface (where "verify" is as close as one can get in a language that doesn't support first-class interfaces). Using can reduces the need to litter classes with predicates that are only there for purposes of testing.

      I never cared for this style of testing. Just call the blasted method and if the test script dies it's not there.

      ----
      : () { :|:& };:

      Note: All code is untested, unless otherwise stated

Re: When I use "can"
by hv (Prior) on Apr 08, 2004 at 13:53 UTC

    Checking my current work application, the main reason I use can is when I'm about to call something that needs a callback supplied:

    # template->capture(pattern, object, callback) # - replace each occurrence of <pattern> in the template # with the result of calling <callback> on <object> $template->capture('%id%', $self, $self->can('id'));
    Note that in this situation, I know that the object must support the method.

    The other 3 uses each use only the boolean result:

    • in one delegating AUTOLOAD, purely to avoid the error message for an unknown method referring to the delegate;

    • in one virtual class to update a timestamp if the actual instance supports that timestamp;

    • in a debug method to shorten the output if the object being dumped supports an 'id' method.

    (I also have three AUTOLOAD subs defined in the same application: the one described above; one for a 'security wrapper' class that pretends to be the wrapped object but blows up if you attempt to call any unpermitted methods; and one dummy object (which also provides its own can method) to allow some parts of the application to be used on an uninstalled copy.)

    Hugo

Re: When I use "can"
by tilly (Archbishop) on Apr 07, 2004 at 15:20 UTC
    My list is even shorter.

    I have no routine uses for can() in my code. I likewise have no routine uses for AUTOLOAD in my code.

    I have never had occasion to use can() in production code. I have used AUTOLOAD in production within the last 6 months. The case where I used AUTOLOAD was one where I did not see the need to support can(), and furthermore was one where many uses of can() that I have seen others use would be inappropriate. (In other words supporting can() would probably be an unwise thing to do.)

    In case anyone is interested, it was essentially a version of Class::Null that handles chaining method calls. (In other words any call on a null object returns another null object.)

Re: When I use "can"
by Beechbone (Friar) on Apr 18, 2004 at 00:52 UTC
    I also use can() to take references to methods. Such as in:
    if ($whatever) { $self->{callback} = $self->can('a'); } else { $self->{callback} = sub {1}; }
    Or to use optimization if possible:
    open F, '>', $self->{filename}; if ($other->can('fetch')) { print F, $other->fetch(); } else { while (my $line = $other->read()) { print F, $line; } } close F;

    Search, Ask, Know