newbie: inheritance

  • Thread starter Andrew V. Tkachenko
  • Start date
A

Andrew V. Tkachenko

Hello.
I'm a bit confused with the following problem:

Lets pretend that I have three modules:

###############
package myDaemon;
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = ref($proto) ? $proto : {};
bless ($self, $class);
}
sub request {
my $self = shift;

my $data;
# some useful things like prepare $data content etc.

$self->_send_request($data);
}

sub _send_request {}
1;
#####################
package myDaemon::INET;
use strict;
use IO::Socket::INET;
our @ISA = qw/myDaemon/;

sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
# some configuration steps for INET socket
my $self = bless $proto->SUPER::new(@_), $class;
}
sub _send_request {
my ($self, $data) = @_;
# send $data via INET socket
}
1;
######################
package myDaemon::UNIX;
use strict;
use IO::Socket::UNIX;
our @ISA = qw/myDaemon/;

sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
# some configuration steps for UNIX socket
my $self = bless $proto->SUPER::new(@_), $class;
}
sub _send_request {
my ($self, $data) = @_;
# send $data via UNIX socket
}
1;
######################


Now I need to add more functionality to myDaemon package: I
need to track all requests and store them in some way
I think about overload myDaemon 'request' method:

##########################
package myLogDaemon;

use strict;
use myDaemon;
our @ISA = qw/myDaemon/;

sub request {
my $self = shift;
# dogin some logging
return $self->SUPER::request(@_);
}
###########################

But. How can I call myDaemon::Socket::INET->new in a way wich will let
me use overloaded 'request' method ?
Seems like I'm absolutely wrong with OO Perl but can't imagine
how to solve this problem :(

Any advice will be greatly appreciated.

Andrew.
 
A

Anno Siegel

Andrew V. Tkachenko said:
Hello.
I'm a bit confused with the following problem:

Lets pretend that I have three modules:

[lots of code snipped]

Please reduce your problem to a small example. You presented much more
code than most people will want to read in a usenet posting.
Now I need to add more functionality to myDaemon package: I
need to track all requests and store them in some way
I think about overload myDaemon 'request' method:

You mean "override". "Overload" is something else.
##########################
package myLogDaemon;

use strict;
use myDaemon;
our @ISA = qw/myDaemon/;

sub request {
my $self = shift;
# dogin some logging
return $self->SUPER::request(@_);
}
###########################

But. How can I call myDaemon::Socket::INET->new in a way wich will let
me use overloaded 'request' method ?

You call the "new" method through inheritance from your subclass. When you
create an object as

my $dem = MyLogDemon->new( ...);

it calls, through inheritance, myDaemon::Socket::INET::new, which creates
a MyLogDemon object (not a myDaemon::Socket::INET object). It (the
created object) will use all of the inherited methods, except for the
overridden "request".

That is why a good "new" method painstakingly keeps track of the
calling package, instead of blindly blessing into its own. Your
own "new" method(s) (which I snipped) do that.
Seems like I'm absolutely wrong with OO Perl but can't imagine
how to solve this problem :(

Not "absolutely wrong", but you seem to be missing a link about inheritance.

Anno
 
A

Andrew V. Tkachenko

Thanks for your reply, Anno.

I'm still confused with this thing.


Anno said:
Andrew V. Tkachenko said:
Hello.
I'm a bit confused with the following problem:

Lets pretend that I have three modules:


[lots of code snipped]

Please reduce your problem to a small example. You presented much more
code than most people will want to read in a usenet posting.

Ok, in a short terms:

1. I have base class myDaemon;

myDaemon

wich has dumb method 'send_request':

sub myDaemon::send_request {}

and non-empty 'request' method:

sub myDaemon::request {}

2. I have two classes wich inherit myDaemon class:

myDaemon::Socket::INET
myDaemon::Socket::UNIX;

each class define its own 'send_request' method

sub myDaemon::Socket::INET::send_request {}
sub myDaemon::Socket::UNIX::send_request {}


3. I can get an instance of myDaemon using either calling
myDaemon::Socket::INET->new
or
myDaemon::Socket::UNIX->new

4. I have another class: myLogDaemon wich inherits from myDaemon and
overrides its 'request' method

You call the "new" method through inheritance from your subclass. When you
create an object as

my $dem = MyLogDemon->new( ...);

it calls, through inheritance, myDaemon::Socket::INET::new, which creates
a MyLogDemon object (not a myDaemon::Socket::INET object). It (the
created object) will use all of the inherited methods, except for the
overridden "request".

But MyLogDemon->new will return object of myDaemon class. It knows
nothing about myDaemon::Socket::INET and myDaemon::Socket::UNIX classes.


Q: I can't imagine how I can get an instance of myLogDaemon calling
::INET->new or ::UNIX->new constructors, because

Thanks for advance,

Andrew.
 
A

Anno Siegel

Andrew V. Tkachenko said:
Thanks for your reply, Anno.

I'm still confused with this thing.


Anno said:
Andrew V. Tkachenko said:
Hello.
I'm a bit confused with the following problem:

Lets pretend that I have three modules:


[lots of code snipped]

Please reduce your problem to a small example. You presented much more
code than most people will want to read in a usenet posting.

Ok, in a short terms:

I am still not sure what you want to accomplish.
1. I have base class myDaemon;

myDaemon

wich has dumb method 'send_request':

sub myDaemon::send_request {}

and non-empty 'request' method:

sub myDaemon::request {}

2. I have two classes wich inherit myDaemon class:

myDaemon::Socket::INET
myDaemon::Socket::UNIX;

each class define its own 'send_request' method

sub myDaemon::Socket::INET::send_request {}
sub myDaemon::Socket::UNIX::send_request {}


3. I can get an instance of myDaemon using either calling

myDaemon::Socket::INET->new
or
myDaemon::Socket::UNIX->new

This doesn't look right. The new() method should always return an object
of the class it is called from and not "know better" and supplant another.

So "myDaemon::Socket::INET->new" should return an object in class
"myDaemon::Socket::INET" and "myDaemon::Socket::UNIX->new" should return
an object in "myDaemon::Socket::UNIX".
4. I have another class: myLogDaemon wich inherits from myDaemon and
overrides its 'request' method

So you introduce a third class that also inherits from myDaemon. That
isn't going to change the behavior of the other classes
(myDaemon::Socket::INET and myDaemon::Socket::UNIX) that already inherit
from it. They don't even know about the new class.

You may have better chances when you turn things around. Write a generic
class myDaemon::Basic that does everything except the logging. Then
create a class myDaemon that (at first) inherits everything from
myDaemon::Basic, and make *that* a base class of myDaemon::Socket::INET
and myDaemon::Socket::UNIX.

Now you can extend the functionality of myDaemon beyond that of
myDaemon::Basic by overriding the corresponding methods in myDaemon.

Anno
 
E

Eric Schwartz

Why do they still put it in the docs (perltoot) anyway?

Okay, I'll bite. I hardly write any OO perl these days (I find ruby
does the trick for me, when I need OO-ness), but the article Randal
referred to says little more than his comment, basically "don't do
this". Why not?

I agree that it's easy enough to work around, thanks to Randal's
article explaining how, but I don't see what's wrong with the above
code.

-=Eric
 
B

Ben Morrow

Eric Schwartz said:
Okay, I'll bite. I hardly write any OO perl these days (I find ruby
does the trick for me, when I need OO-ness), but the article Randal
referred to says little more than his comment, basically "don't do
this". Why not?

I agree that it's easy enough to work around, thanks to Randal's
article explaining how, but I don't see what's wrong with the above
code.

Randal's argument is that the semantics of $obj->new are unclear: does
this copy the object, or create a new clean one? Given that, the former
should be handled with a ->clone instance method, and the latter with
(ref $obj)->new, neither of which is ambiguous.

Ben
 
E

Eric Schwartz

Ben Morrow said:
Randal's argument is that the semantics of $obj->new are unclear: does
this copy the object, or create a new clean one? Given that, the former
should be handled with a ->clone instance method, and the latter with
(ref $obj)->new, neither of which is ambiguous.

That makes perfect sense, thanks. I agree completely now that you've
explained it that way.

-=Eric
 
A

Anno Siegel

Eric Schwartz said:
That makes perfect sense, thanks. I agree completely now that you've
explained it that way.

If god had intended "new" to work this way, "bless" would accept an object
as its second parameter and bless into its class.

Anno
 
B

Ben Morrow

If god had intended "new" to work this way, "bless" would accept an object
as its second parameter and bless into its class.

FVO God == Larry, of course :)

Ben
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,266
Messages
2,571,082
Members
48,773
Latest member
Kaybee

Latest Threads

Top