On Wed, May 31, 2017 10:18 pm, Craig Ringer wrote:
> On 31 May 2017 at 08:43, Craig Ringer <> wrote:
>> Hi all
>> More and more I'm finding it useful to extend PostgresNode for project
>> specific helper classes. But PostgresNode::get_new_node is a factory
>> that doesn't provide any mechanism for overriding, so you have to
>> create a PostgresNode then re-bless it as your desired subclass. Ugly.
>> The attached patch allows an optional second argument, a class name,
>> to be passed to PostgresNode::get_new_node . It's instantiated instead
>> of PostgresNode if supplied. Its 'new' constructor must take the same
>> arguments.
> Note that you can achieve the same effect w/o patching
>, albeit in a somewhat ugly manner, by re-blessing the
> returned object.
> sub get_new_mywhatever_node {
>         my $self = PostgresNode::get_new_node($name);
>         $self = bless $self, 'MyWhateverNode';
>         return $self;
> }
> so this would be cosmetically nice, but far from functionally vital.

It's good style in Perl to have constructors bless new objects with the
class that is passed in, tho.

(I'd even go so far as to say that any Perl OO code that uses fixed class
names is broken).

While technically you can rebless a returned object, that breaks thge
subclassing, sometimes subtle, and sometimes really bad.

For instances, any method calls the constructor does, are happening in the
"hardcoded" package, not in the subclass you are using, because the
reblessing happens later.

Consider for instance:

 package MyBase;

 sub new
    my $self = bless {}, 'MyBase';
    # it should be instead:
    # my $self = bless {}, shift;

 sub _init
    my ($self) = @_;

    $self->{foo} = 'bar';

    # return the initialized object

If you do the this:

 package MySubclass;

 use MyBase;
 use vars qw/@ISA/;

 @ISA = qw/MyBase/;

 sub _init
    my ($self) = @_;

    # call the base's _init

    # initialize our own stuff and override some
    $self->{foo} = 'subclass';
    $self->{baz} = 1;

    # return the initialized object

and try to use it like this:

  package main;

  use MySubclass;

  my $thingy = MySubclass->new();
  print $thingy->{foo},"\n";

you get "bar", not "subclass" - even if you rebless $thingy into the
correct class.

And as someone who subclasses MyBase, you have no idea why or how and it
will break with the next update to MyBase's code. While technically you
can work around that by "peeking" into MyBase's code and maybe some
reblessing, the point is that you shouldn't do nor need to do this.

Please SEE:



Sent via pgsql-hackers mailing list (
To make changes to your subscription:

Reply via email to