Re: Glib::Object::Subclass and Exporter



Le lundi 10 septembre 2012 Ã 09:07 +1000, Kevin Ryde a Ãcrit :
And putting itself at the start of the caller's @ISA ...

Right, and by the way, imho, this should not be done. It is confusing
for the user. Any modification to @ISA should be done either directly by
the user, or by its use of 'base' or 'parent' features.
But then, afaik, these features don't allow passing arguments to the
parent module (do they?), and incidentally Glib wouldn't be able to call
Glib::Type->register_object correctly.

In my idea, the best scenario for extending Gtk/Glib modules would be
something like:
        use parent qw/Gtk2::SomeWidget/;

        our %signals = (
                ...
        );

        our %properties = (
                ...
        );

        ...

But how to get there is not the subject, and i guess that if
Glib::Object::Subclass exists is because such thing would just not work
that easily.

I get some joy from changing it to

    unshift @ISA, qw(Exporter);

so that Exporter is at the start of @ISA and everything from
Glib::Object::Subclass follows.

When i do that, i get 'Variable "@ISA" is not imported' (??).

Still, you're absolutely right about that, and i should better do
something like 'use parent Exporter;', which would setup @ISA for me (as
a matter of fact, this is what i do now).

Anyway, we still won't get Exporter's 'import' sub, it is masked by
Glib::Object::Subclass just as if our module defined one.
Exporter offers a way to deal with it by providing the 'export_to_level'
sub, Glib::Object::Subclass simply doesn't deal with it, and imho this
is bad behavior.

Perhaps the way Glib::Object::Subclass pushes itself onto @ISA to get a
perlish new() could be better done by pushing a separate class which had
only new().  Then any import() in the caller, or the caller's
inheritance, wouldn't be affected in the way you struck.

That would be a solution.
If i modify Glib::Object::Subclass.pm like this:

        package Glib::Object::Base;

        *new = \&Glib::Object::new;

        package Glib::Object::Subclass;

        sub import {
           my ($superclass, %arg) = @_;
           my $class = caller;

           Glib::Type->register_object(
              $superclass, $class,
              %arg,
           );

           # ensure that we have a perlish new().  the old version of this
           # code used a CHECK block to put a new() in if we didn't already
           # have one in the package, but it may be too late to run a CHECK
           # block when we get here.  so, we use the old-fashioned way...
           unshift @{ $class."::ISA" }, qw/Glib::Object::Base/;
        }

Then i have no problem.
Note there is no testing that $ _[0] != Glib::Object::Subclass anymore,
since it is out of @ISA, this won't happen.

Now, the only thing that actually really happens in that 'import' sub is
the call to Glib::Type->register_object.
Does it have to be called _before_ the class definition, or can we do
that in the 'new' sub? So that we can get rid of import, and just get
to:
        use parent qw/Glib::Object::Subclass Gtk2::SomeWidget/;
        our %signals = ( ... );
        ...
That would be a nice step toward the 'use parent qw/Gtk2::SomeWidget/'
scenario i exposed at the beginning of this mail.

In practice I suspect Exporter is not much used with oopery.  Constants
can be offered as class methods

    $c = Foo::Bar->SOME_CONST;

which has the advantage of working from instances too

    $c = $foo->SOME_CONST;

Such a call is a very tiny bit slower (and won't constant-fold), but has
the advantage that further subclasses can override.

Well, the reason i want to export them is, indeed, to avoid the need to
access them by the package namespace.
This will, of course, be made an optional import using import tags.

Exporter is perfectly fine with oop, as long as you don't impose stuff
to be exported, polluting child classes;
And since an 'import' sub is defined, it is just the same as using
Exporter, because that's just what it is: a convenient way to define an
'import' sub.
So if Exporter should be avoided in oop, so is import, and
Glib::Object::Subclass is still doing something wrong.

        bless($self, $class);

This ought to be unnecessary.  If it is necessary then you're either
doing something wrong, or something very advanced :-).

I didn't even thought to check if that was needed, thanks for the info.




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]