* [PATCH] Git.pm: do not break inheritance
@ 2008-10-18 18:25 Christian Jaeger
2008-10-18 20:50 ` Junio C Hamano
0 siblings, 1 reply; 3+ messages in thread
From: Christian Jaeger @ 2008-10-18 18:25 UTC (permalink / raw)
To: git; +Cc: Petr Baudis
Make it possible to write subclasses of Git.pm
Signed-off-by: Christian Jaeger <christian@jaeger.mine.nu>
---
I don't really know what the reason for the _maybe_self behaviour
was; I'm hoping this fix doesn't break anything, I haven't run any
tests with it except with my own code; the fix works on the
assumptions that if an object does indeed have Git.pm in it's
ancestry, _maybe_self should work just as if the object is a 'Git'
object without inheritance.
I'm currently using the following hack to make my scripts be able to
inherit from a non-patched Git.pm: I inherit instead from a wrapper
around Git.pm which inherits from and patches the latter at runtime
using this code:
if (do {
my @res= Git::_maybe_self ( (bless {}, __PACKAGE__) );
not $res[0]
}) {
#warn "patching Git.pm";#
no warnings;
*Git::_maybe_self= sub {
UNIVERSAL::isa($_[0], 'Git') ? @_ : (undef, @_);
}
}
While this currently works, a proper fix would of course be
preferable (like: when in the future will the above hack break?..).
perl/Git.pm | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/perl/Git.pm b/perl/Git.pm
index 6aab712..ba94453 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -1203,8 +1203,7 @@ either version 2, or (at your option) any later version.
# the method was called upon an instance and (undef, @args) if
# it was called directly.
sub _maybe_self {
- # This breaks inheritance. Oh well.
- ref $_[0] eq 'Git' ? @_ : (undef, @_);
+ UNIVERSAL::isa($_[0], 'Git') ? @_ : (undef, @_);
}
# Check if the command id is something reasonable.
--
1.6.0.2
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] Git.pm: do not break inheritance
2008-10-18 18:25 [PATCH] Git.pm: do not break inheritance Christian Jaeger
@ 2008-10-18 20:50 ` Junio C Hamano
2008-10-18 22:21 ` Christian Jaeger
0 siblings, 1 reply; 3+ messages in thread
From: Junio C Hamano @ 2008-10-18 20:50 UTC (permalink / raw)
To: Christian Jaeger; +Cc: git, Petr Baudis
Christian Jaeger <christian@jaeger.mine.nu> writes:
> Make it possible to write subclasses of Git.pm
>
> Signed-off-by: Christian Jaeger <christian@jaeger.mine.nu>
> ---
>
> I don't really know what the reason for the _maybe_self behaviour
> was; I'm hoping this fix doesn't break anything,
That's how you would write class methods, isn't it? IOW, your callers
can say:
my $self = new Git();
$self->method(qw(a b c));
Git::method(qw(a b c))
and you can start your method like this:
sub method {
my ($self, @args) = _maybe_self(@_)
...
}
and use @args the same way for either form of the call in the
implementation. Two obvious pitfalls are:
- You cannot use $self if you set up your parameters with _maybe_self;
- The second form of the call would call directly into Git::method, never
your subclasses implementation, even if you write:
use Git;
package CJGit;
our @ISA = qw(Git);
sub method {
...
}
> sub _maybe_self {
> - # This breaks inheritance. Oh well.
> - ref $_[0] eq 'Git' ? @_ : (undef, @_);
> + UNIVERSAL::isa($_[0], 'Git') ? @_ : (undef, @_);
> }
>
> # Check if the command id is something reasonable.
The patch looks Ok, as long as you have a working UNIVERSAL::isa() in your
version of Perl. My reading of perl561delta,pod says that Perl 5.6.1 and
later should have a working implementation.
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] Git.pm: do not break inheritance
2008-10-18 20:50 ` Junio C Hamano
@ 2008-10-18 22:21 ` Christian Jaeger
0 siblings, 0 replies; 3+ messages in thread
From: Christian Jaeger @ 2008-10-18 22:21 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Petr Baudis
Junio C Hamano wrote:
> That's how you would write class methods, isn't it? IOW, your callers
> can say:
>
> my $self = new Git();
> $self->method(qw(a b c));
> Git::method(qw(a b c))
>
> and you can start your method like this:
>
> sub method {
> my ($self, @args) = _maybe_self(@_)
> ...
> }
>
> and use @args the same way for either form of the call in the
> implementation.
I see, a magic way to offer both an OO and procedural api. Well, partial
procedural api, since not all of the methods can work without the $self.
> Two obvious pitfalls are:
>
> - You cannot use $self if you set up your parameters with _maybe_self;
>
> - The second form of the call would call directly into Git::method, never
> your subclasses implementation, even if you write:
>
> use Git;
> package CJGit;
> our @ISA = qw(Git);
>
> sub method {
> ...
> }
>
>
(This is no problem iff people are calling procedures in object notation
if they actually have got an object at hands. I.e. if you've got some
code which does:
my $repo= Git->repository(...);
$repo->foo;
then all is fine, and I would think it would be weird if people called
Git::foo($repo, ... ) in such a case. Well for my purposes it's not a
problem anyway, since if a user wants to use the extensions, he needs to
actually do this:
my $repo= CJGit->repository(...);
and then it should be clear that one shouldn't call Git:: directly. The
problem will only be in cases where an extended object is being fed to
existing code which calls Git:: with objects in the hope that virtual
method calls are going to the extended class; well, let's fix those bad
call sites when they are being discovered... Maybe this warrants a
warning somewhere.)
>> sub _maybe_self {
>> - # This breaks inheritance. Oh well.
>> - ref $_[0] eq 'Git' ? @_ : (undef, @_);
>> + UNIVERSAL::isa($_[0], 'Git') ? @_ : (undef, @_);
>> }
>>
>> # Check if the command id is something reasonable.
>>
>
> The patch looks Ok, as long as you have a working UNIVERSAL::isa() in your
> version of Perl. My reading of perl561delta,pod says that Perl 5.6.1 and
> later should have a working implementation.
>
From http://perldoc.perl.org/perl561delta.html:
> UNIVERSAL::isa()
>
> A bug in the caching mechanism used by UNIVERSAL::isa() that affected
> base.pm has been fixed. The bug has existed since the 5.005 releases,
> but wasn't tickled by base.pm in those releases.
This looks like only a bug in some (corner?) cases; I've verified that
I've been using the isa() method *or* function since perl 5.005_03, and
haven't had issues with it. I can't easily verify though when I switched
from
#if (Scalar::Util::blessed($value) and $value->isa("Eile::Html")) {
to
if (UNIVERSAL::isa($value,"Eile::Html")) {
(because it was simpler to write, once I discovered that I could just
call the function directly instead of relying on method dispatch) but
that might not have made a difference.
Christian.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2008-10-18 22:23 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-10-18 18:25 [PATCH] Git.pm: do not break inheritance Christian Jaeger
2008-10-18 20:50 ` Junio C Hamano
2008-10-18 22:21 ` Christian Jaeger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).