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

Why doesn't use base call import?

22 views
Skip to first unread message

Peter Scott

unread,
Mar 13, 2003, 8:11:05 PM3/13/03
to
I had a class which defined some constants and used them in various methods.
Then I discovered another class which needed the same constants for different
methods. So I made a superclass for them to inherit from, put the common
methods in there, and figured that if each one did a

use base qw(SuperClass);

and SuperClass did

use base qw(Exporter);
our @EXPORT = qw(constant...);

I'd be done. But it didn't work. I found a lively discussion on exactly this matter:

http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&threadm=F150mqn4pxUm1Ueqjaa0000c045%40hotmail.com&rnum=8&prev=/groups%3Fq%3Dperl%2B%2522use%2Bbase%2522%2Bimport%2Brequire%26hl%3Den%26lr%3D%26ie%3DUTF-8%26selm%3DF150mqn4pxUm1Ueqjaa0000c045%2540hotmail.com%26rnum%3D8

But what wasn't mentioned is that the reason is that use base doesn't call import().
There I'd been thinking that it was roughly equivalent to

BEGIN { use SuperClass; push @ISA, qw(SuperClass) }

whereas in fact its own documentation says it's really

BEGIN { require SuperClass; push @ISA, qw(SuperClass) }

Fine. But can someone tell me why use base doesn't or shouldn't call import()
on the superclasses? The common idiom for subclassing prior to use base was:

use SuperClass;
our @ISA = qw(SuperClass);

and I didn't hear anyone complaining that that called SuperClass->import.

--
Peter Scott

John Douglas Porter

unread,
Mar 13, 2003, 11:12:59 PM3/13/03
to

Peter Scott <pe...@PSDT.com> wrote:
> ... can someone tell me why use base doesn't or shouldn't
> call import()

I'm not in a position to say what all the rationale may have
been... but I can offer this: that importing symbols (as e.g.
via Exporter) is orthogonal and contrary to object-oriented
programming -- which is presumably what you're doing if you're
use'ing base.

--
John Douglas Porter


__________________________________________________
Do you Yahoo!?
Yahoo! Web Hosting - establish your business online
http://webhosting.yahoo.com

Ben Kennedy

unread,
Mar 18, 2003, 6:36:29 PM3/18/03
to

"Peter Scott" <pe...@PSDT.com> wrote in message
news:J_9ca.214263$na.92...@news2.calgary.shaw.ca...

>
> Fine. But can someone tell me why use base doesn't or shouldn't call
import()
> on the superclasses? The common idiom for subclassing prior to use base
was:
>
> use SuperClass;
> our @ISA = qw(SuperClass);
>
> and I didn't hear anyone complaining that that called SuperClass->import.

I think the "use base" behavior makes more sense from an OO standpoint,
simply because global constants are not very OO-ish to begin with (IMO). On
the other hand, static member variables are fine by OO standards and work
niceley with 'use base' and constants:

package SuperClass;

use constant FOO_MAX => 7;

package MyClass;

use base 'SuperClass';

sub some_method {
my $self = shift;
print "Max number of FOOs: " . $self->FOO_MAX . "\n";
}

People didn't complain about "use" and importing before because "require"
could be the mechanism for bringing in the parent class code. From a
practical standporint, perhaps "use base" chooses "require" because you can
always manually bring in constants yourself, while you can't undo an
"import".

--Ben Kennedy


IBitOBear

unread,
Mar 18, 2003, 6:56:55 PM3/18/03
to
pe...@PSDT.com (Peter Scott) wrote in message news:<J_9ca.214263$na.92...@news2.calgary.shaw.ca>...

> Fine. But can someone tell me why use base doesn't or shouldn't call import()
> on the superclasses? The common idiom for subclassing prior to use base was:
>
> use SuperClass;
> our @ISA = qw(SuperClass);

This is a possibly very flawed guess:

"require" allows for AUTOLOAD and such. That is, requiring a package
without using it lets some things happen "late" in the runtime.

"use" causes compile time evaluation of some of the things that
require doesn't touch.

So the single statement "use base qv(whatever);" is identical to "@ISA
= qw(whatever);" and is identically subject to the presense or absence
of the "use whatever;" or the "require whatever;". That is, if you
don't use it, it's just a word in a list of words to try to search
through for methods.

I can't think of any mention anywhere of an intent that "use base
package;" would relieve the user of needing the "use package;"
semantics.

For all I can tell, it's a one-for-one replacement of @ISA.

Tassilo v. Parseval

unread,
Mar 19, 2003, 1:07:40 AM3/19/03
to
Also sprach IBitOBear:

> So the single statement "use base qv(whatever);" is identical to "@ISA
>= qw(whatever);" and is identically subject to the presense or absence
> of the "use whatever;" or the "require whatever;". That is, if you
> don't use it, it's just a word in a list of words to try to search
> through for methods.
>
> I can't think of any mention anywhere of an intent that "use base
> package;" would relieve the user of needing the "use package;"
> semantics.

Did you have a look in the most obvious spot (perldoc base)?

SYNOPSIS
package Baz;
use base qw(Foo Bar);

DESCRIPTION
Roughly similar in effect to

BEGIN {
require Foo;
require Bar;
push @ISA, qw(Foo Bar);
}

[...]
If any of the base classes are not loaded yet, *base* silently
"require"s them.

Thus, there is no longer the need for use()ing a module.

> For all I can tell, it's a one-for-one replacement of @ISA.

Not at all.

Tassilo
--
$_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
$_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval

Peter Scott

unread,
Mar 19, 2003, 9:52:55 AM3/19/03
to
In article <RA2dnfD4pau...@giganews.com>,

True, but it appears at best debatable, and I can't find any evidence
that it was debated. Forget the example of exported constants for a
moment and just consider whether or not base should call import. Maybe
the most common kind of import() is one that's inherited from Exporter,
but it doesn't have to be; in general it's more like an initializer for
the class.

If you're going to provide a convenience pragma for loading the module
at the same time as inheriting from it, it seems to make more sense
to call that initializer than not to. The superclass might be some
database package, for instance, and its import() opens a connection
because it happens to be a singleton class. Bad design? I dunno.
But I'd be wondering why my subclass that was just overriding some
picayune method didn't work.

I think it boils down to the principle of least surprise. Maybe I'm
just easily surprised :-)

--
Peter Scott

Ben Kennedy

unread,
Mar 19, 2003, 1:34:20 PM3/19/03
to

"Peter Scott" <pe...@PSDT.com> wrote in message
news:bv%da.505248$Yo4.28...@news1.calgary.shaw.ca...

> Maybe
> the most common kind of import() is one that's inherited from Exporter,
> but it doesn't have to be; in general it's more like an initializer for
> the class.

> ...


> If you're going to provide a convenience pragma for loading the module
> at the same time as inheriting from it, it seems to make more sense
> to call that initializer than not to. The superclass might be some
> database package, for instance, and its import() opens a connection
> because it happens to be a singleton class. Bad design? I dunno.
> But I'd be wondering why my subclass that was just overriding some
> picayune method didn't work.

The purpose of import() is quite clear - it should only be dealing the
namespace issues. Class initialzion should happen somewhere else. Now
there are two kinds of initialization, per-instance and class-level.
Class-level initailzation doesn't even need to be in a function, it can just
be in the code itself, in which case it will run by 'use' and 'require'.
However, for what its worth, I don't even bother with that anymore and just
have a "Singleton" base class that has a static method to returned a cached
copy of an object, e.g.

package Some::Object;

use base 'SomeSingletonClass';

package SomeSingletonClass;

my %cache;
sub get_cached_instance {
my $package = shift;
# cache object in %cache hash or return pre-constructed cached object
}

....

my $obj = Some::Object->get_cached_instance->some_method_name

This lets me write code with expensive initialization built in as part of
the object without worrying about sharing resources. Basically, every time
I thought "Gee, all my objects of type FOO should share this same resource",
I could just as easily say "All my objects that need a type FOO can share
the same object" - in other words, I let the calling code determine whether
or not to use my code as a singleton class or not. If two instances of a
class absolutely need access to a shared resource, the solution would be to
factor out the resource into it's own class, and use the
"get_cached_instance" mechanism. Another nice side-effect is you can wipe
your cache of objects with a single command, which is great when forking.
This really fixed all my class-initialization concerns. Anyway, hope some
of this helps you--

--Ben Kennedy

IBitOBear

unread,
Mar 28, 2003, 12:38:02 AM3/28/03
to
"Tassilo v. Parseval" <tassilo....@rwth-aachen.de> wrote in message news:<b591fc$rrg$1...@nets3.rz.RWTH-Aachen.DE>...

> SYNOPSIS
> package Baz;
> use base qw(Foo Bar);
> DESCRIPTION
> Roughly similar in effect to
>
> BEGIN {
> require Foo;
> require Bar;
> push @ISA, qw(Foo Bar);
> }
>
> [...]
> If any of the base classes are not loaded yet, *base* silently
> "require"s them.
>
> Thus, there is no longer the need for use()ing a module.


Sorry to correct but...

There is still a need to to "use" the module.

from "man perlmod"...
"use Foo;" is equivalant to "BEGIN { require Foo; import Foo; }"

and as you state above
"use base Foo;" is equivalant to "BEGIN { require Foo; push @ISA
qw(Foo)}"

Notice the absence of "import Foo;" from the second example.

SO if you care about having whatever the import does in Foo done for
you, you had better "use Foo;" before you "use base Foo;"

If you don't you'll regret it. (Which takes us back to the original
questioner's problem... 8-)

Rob.

0 new messages