http://www.perlmonks.org?node_id=863856

cbanker has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to set up a general wrapper for multiple hardware devices that can interface with different device drivers based on the name specified in the new() call. For example, calling DeviceClass->new("Device1") from the main program would use a device with driver module Device1 and DeviceClass->new("Device2") would use a device with driver module Device2.

What seems to be complicating this is the fact that the Device# driver modules (Device1 and Device2 in this example) are shared components that are not mine and are not object-oriented (my modules such as DeviceClass are OO though). I'd prefer to keep these files as they are so as not to affect other scripts that use them.

I tried the following but haven't had any luck, probably because the device modules are not object oriented.

... if ('Device1' eq $device){ use Device1; @ISA = qw(Device1); } elsif ('Device2' eq $device){ use Device2; @ISA = qw(Device2); } ...

I also looked at the aliased module, but that doesn't seem to be an option for working with non-OO modules.

Given these constraints, is there any way for DeviceClass to have access to all of the functions in Device# and to call those functions from within the functions in DeviceClass?

Replies are listed 'Best First'.
Re: Inheritance based on input
by Fletch (Bishop) on Oct 06, 2010 at 19:32 UTC

    Sounds like you're looking for something along the lines of the Adapter pattern (and/or the Facade pattern). Your DeviceClass would be a factory which returns instances of DeviceAdapter::Device1 or what not; DeviceAdapter::Foo would convert from your generic interface into the correct calls on a Foo instance, DeviceAdapter::Bar similar for Bar instances.

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

Re: Inheritance based on input
by Corion (Patriarch) on Oct 06, 2010 at 19:31 UTC

    use won't work here. Look at require (and import). By using something like the following, you can import modules and call functions in them on demand:

    ... if ($device =~ /^(Device1|Device2)$/){ require "$device.pm"; $device->import(); # import the device subroutines here } ... # This assumes all devices have and export the same subroutine names device_function_1(); device_function_2();

    Update: Fixed typo in regex, thanks to Perlbotics

Re: Inheritance based on input
by moritz (Cardinal) on Oct 06, 2010 at 19:36 UTC
    Since one module is not object oriented, inheriting from it doesn't make sense.

    If it follows a pattern that can be automatically wrapped into an OO fashion, you can create an automatic wrapper based on AUTOLOAD (see perlsub).

    Instead of magically inheriting from one class or another, it might be easier to have an attribute that stores the device driver in question, and then work with delegation from there on.

    Perl 6 - links to (nearly) everything that is Perl 6.