Inner classes, sort of?

F

fishfry

Sometimes you have a class with a method that returns a list of
identical hashes, like this ...

sub listOfItems {
push @items, {_name => "larry", _value => 47};
push @items, {_name => "curly", _value => 93};
push @items, {_name => "moe", _value => 12};

return \@items;
}

The caller is going to iterate through the list and access the data like
this:

$items = listOfItems();
foreach $item (@$items) {
$name = $item->{_name};
}

For reasons of encapsulation and object-purity and so forth, you don't
want the caller to do that ... you'd rather have them write

$name = $item->name();

In order to do that, you'd have to make a separate package to define a
class for the name/value hash. But that's sort of an overkill ... not
every little hash deserves to be a class.

I'm wondering if there is some way to make the name/value hash a
mini-class somehow, so that you could define accessor methods, without
having to write a full-blown package that blesses the hash into a class.

I believe in Java this would be called an inner class. Is that right?
And on CPAN I've noticed a couple of contributions that say they
implement inner classes.

Is there a clever technique to do what I want? And/or is one of the
inner class CPAN packages appropriate?
 
A

anno4000

fishfry said:
Sometimes you have a class with a method that returns a list of
identical hashes, like this ...

sub listOfItems {
push @items, {_name => "larry", _value => 47};
push @items, {_name => "curly", _value => 93};
push @items, {_name => "moe", _value => 12};

return \@items;
}

The caller is going to iterate through the list and access the data like
this:

$items = listOfItems();
foreach $item (@$items) {
$name = $item->{_name};
}

For reasons of encapsulation and object-purity and so forth, you don't
want the caller to do that ... you'd rather have them write

$name = $item->name();

In order to do that, you'd have to make a separate package to define a
class for the name/value hash. But that's sort of an overkill ... not
every little hash deserves to be a class.

I'm wondering if there is some way to make the name/value hash a
mini-class somehow, so that you could define accessor methods, without
having to write a full-blown package that blesses the hash into a class.

You don't get method calls in Perl without a blessed object, so you
won't get around blessing the hash.

Another problem is that apparently the names you wish to have re-appear
as methods aren't known until run time. That means the class would have
to use some AUTOLOAD() based technique to generate methods on the fly.
That isn't exactly going to be a light-weight implementation. Then
again, why would it have to be?
I believe in Java this would be called an inner class. Is that right?
And on CPAN I've noticed a couple of contributions that say they
implement inner classes.

Is there a clever technique to do what I want? And/or is one of the
inner class CPAN packages appropriate?

That is up to you to decide.

Anno
 
R

Robert 'phaylon' Sedlacek

fishfry said:
I'm wondering if there is some way to make the name/value hash a
mini-class somehow, so that you could define accessor methods, without
having to write a full-blown package that blesses the hash into a class.

Well, there's Class::Struct.


hth, p
 
C

Charles DeRykus

fishfry said:
Sometimes you have a class with a method that returns a list of
identical hashes, like this ...

sub listOfItems {
push @items, {_name => "larry", _value => 47};
push @items, {_name => "curly", _value => 93};
push @items, {_name => "moe", _value => 12};

return \@items;
}

The caller is going to iterate through the list and access the data like
this:

$items = listOfItems();
foreach $item (@$items) {
$name = $item->{_name};
}

For reasons of encapsulation and object-purity and so forth, you don't
want the caller to do that ... you'd rather have them write

$name = $item->name();

In order to do that, you'd have to make a separate package to define a
class for the name/value hash. But that's sort of an overkill ... not
every little hash deserves to be a class.

I'm wondering if there is some way to make the name/value hash a
mini-class somehow, so that you could define accessor methods, without
having to write a full-blown package that blesses the hash into a class.

I believe in Java this would be called an inner class. Is that right?
And on CPAN I've noticed a couple of contributions that say they
implement inner classes.

Is there a clever technique to do what I want? And/or is one of the
inner class CPAN packages appropriate?

If you want to restrict how the list is accessed, couldn't you just
privatize the list and provide special accessors, eg.,


package MyClass;

sub _listOfItems {
push @items, {_name => "larry", _value => 47};
push @items, {_name => "curly", _value => 93};
push @items, {_name => "moe", _value => 12};
}

sub new { ...
_listOfItems(); # populate restricted list
...
}

#
my $index = 0;
sub ListName {
$index = $index >= @items ? 0 : $index;
return $items[$index++]->{_name};
}
sub ListValue {
return unless my $name = $_[1];
for (@items) {
return $_->{_value} if $_->{_name} eq $name;
}
}

...
 
B

Big and Blue

fishfry said:
For reasons of encapsulation and object-purity and so forth, you don't
want the caller to do that ... you'd rather have them write

$name = $item->name();

For purity you probably don't want to do that either.

What you actually want to do tell the Object to perform an action on
each member of its list.

sub my_action {
my $item = shift;

....
}

my $l_obj = MyObject->new(.....);
$l_obj->send_items_to(\&my_action);
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top