Moin, On Wed, May 31, 2017 10:18 pm, Craig Ringer wrote: > On 31 May 2017 at 08:43, Craig Ringer <cr...@2ndquadrant.com> 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 > PostgresNode.pm, 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; $self->_init(); } sub _init { my ($self) = @_; $self->{foo} = 'bar'; # return the initialized object $self; } 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 $self->SUPER::_init(); # initialize our own stuff and override some $self->{foo} = 'subclass'; $self->{baz} = 1; # return the initialized object $self; } 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: http://perldoc.perl.org/perlobj.html Regards, Tels -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers