On Wed, Jan 27, 2010 at 8:41 PM, Lyle <[email protected]> wrote:
>
> For this I can just export methods to the OrigObj's namespace.

True!

> ExtObj::guts was just so that the new_methods didn't get exported to
> OrigObj, and only the ExtObj method did.

Methods won't get exported by ExtObj unless they're listed in @EXPORT
(or @EXPORT_OK etc.). So you can do without ExtObj::guts, although I
guess its existence might serve to help avoid confusion in that ExtObj
contains a function whereas ExtObj::guts is a class.

> But I don't want a huge object full of methods. It's the grouping into sub 
> objects that I'm really after.

> There will only be one $OrigObj, but many $ExtObj, not from the same class, 
> each different with different methods.

> ExtObj only exports one method of the same name to OrigObj. That method 
> returns an object of the ExtObj::guts class, which contains all the 
> new_methods. Only one instance of ExtObj::guts will ever be created and used. 
> It's purely to group similar methods together in sub objects, rather than 
> having a huge object with lots of methods.
>
> I'm aiming for high cohesion and encapsulation, although methods of 
> ExtObj::guts will often have to access $OrigObj. The $extobj object of 
> ExtObj::guts, created in the ExtObj class can only be access through the 
> $OrigObj->ExtObj method and not directly through other $OrigObj methods. 
> (although saying that, I think I might need to wrap "my $extobj;" and the 
> following 2 subs in a block??).

OK, so we want $OrigObj->ExtObj->new_methods to invoke 'new_methods'
in the class 'ExtObj::guts' but provide access to $OrigObj within the
method body.

Might not be what you're after, but here's a way with a couple of
ideas that might be useful?

ExtObj.pm
--
package ExtObj;

use strict;
use warnings;

use Carp;
use Scalar::Util qw( blessed weaken );

sub new {
    my $class = shift;
    my %args  = @_;
    my $self  = bless \%args => $class;
    weaken $self->{ OrigObj };
    return $self;
}

sub OrigObj {
    my $self = shift;
    return $self->{ OrigObj };
}

sub new_methods {
    my $self = shift;
    print "new_methods: $self->{OrigObj}\n";
    $self->some_method; # Will automatically call $self->{OrigObj}->some_method
    return;
}

sub AUTOLOAD {
    my $self = shift;
    our $AUTOLOAD;
    ( my $method = $AUTOLOAD ) =~ s/.*:://ms;
    # Automatically delegate to OrigObj if we can
    if ( $self->OrigObj && $self->OrigObj->can( $method ) ) {
        return $self->OrigObj->$method( @_ );
    }
    # Ignore calls to DESTROY, Perl generates these because of this AUTOLOAD
    if ( $method eq 'DESTROY' ) {
        return;
    }
    my $package = blessed( $self );
    croak qq{Can't locate object method "$method" via package "$package"};
}

1;
--

OrigObj.pm
--
package OrigObj;

use strict;
use warnings;

use ExtObj;

my $OrigObj;

sub new {
    my $class = shift;
    my $self  = bless {} => $class;
    $self->{ ExtObj } = ExtObj->new( OrigObj => $self );
    return $self;
}

sub ExtObj {
    my $self = shift;
    return $self->{ ExtObj };
}

sub instance {
    return $OrigObj ||= __PACKAGE__->new;
}

sub some_method {
    my $self = shift;
    print "some_method: $self\n";
    return;
}

1;

--
Test code:
--
use OrigObj;
my $obj = OrigObj::instance();
$obj->ExtObj->new_methods;

_______________________________________________
BristolBathPM mailing list
[email protected]
http://mailman.bristolbath.org/mailman/listinfo/bristolbathpm

Reply via email to