Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

inheritance problem

10 views
Skip to first unread message

Technical Services - UK Link

unread,
Sep 27, 2000, 3:00:00 AM9/27/00
to
I have a number of modules that have a structure like the example below,
the problem I have with them is that when I call Test1->testing, it
should call Test2->new which in turn should call Test1->new, but for
some reason it only calls Test1->new, can anyone explain to me why this
is happening and tell me what I can do about it?

Kees Vonk

----------------------------------------------------------------------------

package Test1;
use strict;


sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = {};

print "Debug: --> Test1->new\n";

bless ($self,$class);
return $self;
}

sub testing {
my $module = 'Test3';

require "$module.pm";
import $module;

# This should call Test2::new which then calls Test1::new,
# but Test2::new never seems to be called.
my $test3 = new $module;
}

1;

----------------------------------------------------------------------------

package Test2;
use strict;

use Test1;
use vars qw(@ISA);
@ISA = qw(Test1);

sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = $class->SUPER::new;

print "Debug: --> Test2->new\n";

bless $self, $class;
return $self;
}

1;

----------------------------------------------------------------------------

package Test3;
use strict;

use Test2;
use vars qw(@ISA);
@ISA = qw(Test2);

1;

----------------------------------------------------------------------------

#!/usr/bin/perl -w

use strict;

use Test1;

my $test1 = new Test1;
$test1->testing;

Ren Maddox

unread,
Sep 27, 2000, 3:00:00 AM9/27/00
to
Technical Services - UK Link <fx...@dial.pipex.com> writes:

> I have a number of modules that have a structure like the example below,
> the problem I have with them is that when I call Test1->testing, it
> should call Test2->new which in turn should call Test1->new, but for
> some reason it only calls Test1->new, can anyone explain to me why this
> is happening and tell me what I can do about it?

I believe you are running into a problem with your indirect object
syntax. If you change the call to new as I have indicated, you will
get the desired behavior. With the indirect object syntax, I believe
that $module is being interpreted as a simple argument to the "new"
function in the current package (Test1). All-in-all, it seems best to
simply avoid the indirect object syntax.

The latest Camel has this to say about the indirect object syntax:

"The indirect object syntax is less cluttered, but suffers from
several forms of syntactic ambiguity."

It goes on to list two particular ambiguities, neither of which seems
to explain the behavior you are seeing, but I take that as staunch
enough warning to simply avoid the syntax whenever possible.

[code omitted]


> sub testing {
> my $module = 'Test3';
>
> require "$module.pm";
> import $module;
>
> # This should call Test2::new which then calls Test1::new,
> # but Test2::new never seems to be called.
> my $test3 = new $module;

my $test3 = $module->new;
> }
[more code omitted]

--
Ren Maddox
r...@tivoli.com

Thierry Bezecourt

unread,
Sep 27, 2000, 3:00:00 AM9/27/00
to
At 09:15 27/09/2000 +0100, Technical Services - UK Link wrote:

>package Test1;

(...)

>sub testing {
> my $module = 'Test3';
>
> require "$module.pm";
> import $module;
>
> # This should call Test2::new which then calls Test1::new,
> # but Test2::new never seems to be called.
> my $test3 = new $module;
>}

Because $module is not known at compilation time, the "new" you are calling
on the last line is Test1::new, not Test3::new. Replace the last line with:

my $test3 = eval "new $module";

Or, more clearly:

return eval "new $module";

Note that, for the same reason, when you call "import $module", you invoke
Test1::import with $module (i.e the string "Test3") as an argument, not
Test3::import.

You will find more details about that in the perlmod and Exporter man pages.

Ren Maddox

unread,
Sep 27, 2000, 3:00:00 AM9/27/00
to
Ren Maddox <ren.m...@tivoli.com> writes:

> I believe you are running into a problem with your indirect object
> syntax. If you change the call to new as I have indicated, you will
> get the desired behavior. With the indirect object syntax, I believe
> that $module is being interpreted as a simple argument to the "new"
> function in the current package (Test1). All-in-all, it seems best to
> simply avoid the indirect object syntax.
>
> The latest Camel has this to say about the indirect object syntax:
>
> "The indirect object syntax is less cluttered, but suffers from
> several forms of syntactic ambiguity."
>
> It goes on to list two particular ambiguities, neither of which seems
> to explain the behavior you are seeing, but I take that as staunch
> enough warning to simply avoid the syntax whenever possible.

And I just noticed that on the next page it seems to discuss almost
this exact problem.

"The final syntactic ambiguity with the indirect object style of
method invocation is that it may not be parsed as a method call at
all, because the current package may have a subroutine of the same
name as the method."

It goes on to describe how to disambiguate this situation when using a
literal class name, but that doesn't solve the problem in your
situation. I was able to get it to work with an "eval":

my $test3 = eval "new $module";

This makes the class look like a literal when evaluated, and since it
was already required, there is no ambiguity.

--
Ren Maddox
r...@tivoli.com

Tye McQueen

unread,
Sep 29, 2000, 3:00:00 AM9/29/00
to
) At 09:15 27/09/2000 +0100, Technical Services - UK Link wrote:
) > my $test3 = new $module;

Thierry Bezecourt <th...@thbz.cx> writes:
)
) Because $module is not known at compilation time, the "new" you are calling
) on the last line is Test1::new, not Test3::new. Replace the last line with:
)
) my $test3 = eval "new $module";
)
) Or, more clearly:
)
) return eval "new $module";

Or much more clearly and more efficiently:

return $module->new();

) Note that, for the same reason, when you call "import $module", you invoke
) Test1::import with $module (i.e the string "Test3") as an argument, not
) Test3::import.

$module->import;

Just one of several reason why using indirect object notation is
not a good idea.
--
Tye McQueen Nothing is obvious unless you are overlooking something
http://www.metronet.com/~tye/ (scripts, links, nothing fancy)

0 new messages