in reply to Re: Reversing (some of) inheritance
in thread Reversing (some of) inheritance

I don't even entirely mean OO modules, either. It's more of a "replacement" of a module
If we take that as a "requirement", then any approach whose description includes the words "bless" or "new" is right out.

True - I suppose the idea in non-OO modules would be that you could interject the "correct" code in the right place(s), but that wouldn't necessarily mean you want to replace everything. Which is why I had the "qw(new)" on the use lines above: so that you could say exactly what you wanted to override.

The purpose of this is really to allow me to try and simplify the use of a generic framework, so the only thing that really needs overriding in my case is new, but even then, nothing in perl says you have to use 'new' as your constructor. But, in the same way I'm contemplating taking an existing framework and splitting it into generic and specific pieces so that other departments can use the generic parts, I'm trying to think of how to create this functionality generically.

For example, I have some code running on Windows that needs to create a unix-style path (the output is eventually read and used on a unix box). Obviously, File::Spec->catfile doesn't work. Unless I replaced it. In my case, I had control over the function that was creating the path, so I could just use File::Spec::UNIX->catfile on all platforms instead, so that was fine. But if it were in code that I didn't control, e.g., something from CPAN or even one of the modules that shipped with perl, then replacing File::Spec's catfile, even just temporarily, would be the only thing I can think of that would work. (Ok, I can think of others, but none really any better... doing an s:\\:/:g doesn't necessarily work if the code starts to try to run on, say, MVS.)

So I'm not necessarily thinking that every function needs to be replaced in the "parent" module. Merely an arbitrary subset (where "subset" has the mathematical meaning: set X is a subset of itself). And now I'm also thinking that a "no" (unimport) method should be there, too, to undo it.

Also, I have problems with duplicate information, and related information in separate locations. My problem, then, with the factory module is that adding or changing subclasses means changing a separate, otherwise unrelated, file: the factory module. Being able to "use Module::Replace Base::Package qw(...)" means that it's colocated with the module that would otherwise be created via the factory. Rename the module? No problem. Add a new module? If this is part of the standard template used for modules, your work is already done.

Heck, even in factory setup, I'd be tempted to initialise the factory method in BEGIN blocks in the modules that the factory would initialise. And that would be ugly, too.

Replies are listed 'Best First'.
Re^3: Reversing (some of) inheritance
by jdporter (Paladin) on Apr 23, 2008 at 14:13 UTC
    So I'm not necessarily thinking that every function needs to be replaced in the "parent" module. Merely an arbitrary subset

    Cool; that's what my approach above allows.

    So, I tested the idea using Exporter, and it works just fine. (There is one glitch, though: you get "redefined" warnings which cannot be silenced merely by doing no warnings just before the import call. Apparently Exporter turns on such warnings explicitly. Perhaps someone who is more expert on Exporter can explain how to silence the warnings.)
    Extending it to let the caller define the set of methods to override:

    . . . sub override_Foo { my $pkg = shift; local @Bar::EXPORT = @_; package Foo; # how dare we! Bar->import; } # and then: Bar->override_Foo(qw( new method2 ));