Code Comments
Programming Forum and web based access to our favorite programming groups.
I have a base class called as Weapon and I have derived classes 'Gun'
and 'RocketLauncher'. I need to instantiate Gun or RocketLauncher
based on a parameter say distance from the target. If the distance is
less than 20m I need a gun and if it is more I will need a
RocketLauncher.
This is my attempt at a Perl code that does this. Is this the right
way to do this. Any pointers will be of help.
#! /usr/local/bin/perl -w
package Weapon;
use strict;
sub new {
my ( $self ) = @_;
my $class = ref($self) || $self;
return bless { }, $class;
}
sub hitPoints {
my ( $self ) = @_;
return $self->{hitpoints};
}
sub fire {
my ( $self, $target ) = @_;
print "Destroyed the target !! ", $self->hitPoints;
#$target->hurt($self->hitPoints);
}
package Gun;
use strict;
use base 'Weapon';
sub new {
my ( $self ) = @_;
my $class = ref($self) || $self;
$self = new Weapon();
$self->{type} = 'GUN';
$self->{hitpoints} = 10;
return $self;
}
package RocketLauncher;
use strict;
use base 'Weapon';
sub new {
my ( $self ) = @_;
my $class = ref($self) || $self;
$self = new Weapon();
$self->{type} = 'ROCKET';
$self->{hitpoints} = 100;
return $self;
}
1;
--
For this hour :
Fools ignore complexity. Pragmatists suffer it. Some can avoid it.
Geniuses remove it.
Alan Perlis
Post Follow-up to this messageThens <thens@NOSPAMti.com> wrote in comp.lang.perl.misc:
>
> I have a base class called as Weapon and I have derived classes 'Gun'
> and 'RocketLauncher'. I need to instantiate Gun or RocketLauncher
> based on a parameter say distance from the target. If the distance is
> less than 20m I need a gun and if it is more I will need a
> RocketLauncher.
>
> This is my attempt at a Perl code that does this. Is this the right
> way to do this. Any pointers will be of help.
Do what? I see no attempt to create one or the other depending on a
parameter.
I don't see any gross errors in the class setup. However, you should
switch on warnings as a matter of course. Also, storing the weapon
type in the object is not really necessary, since ref() can always tell
you that.
[code left in place for reference]
Anno
> #! /usr/local/bin/perl -w
>
> package Weapon;
>
> use strict;
>
> sub new {
> my ( $self ) = @_;
> my $class = ref($self) || $self;
> return bless { }, $class;
> }
>
> sub hitPoints {
> my ( $self ) = @_;
> return $self->{hitpoints};
> }
>
> sub fire {
> my ( $self, $target ) = @_;
> print "Destroyed the target !! ", $self->hitPoints;
> #$target->hurt($self->hitPoints);
> }
>
> package Gun;
> use strict;
> use base 'Weapon';
>
> sub new {
> my ( $self ) = @_;
> my $class = ref($self) || $self;
> $self = new Weapon();
>
> $self->{type} = 'GUN';
> $self->{hitpoints} = 10;
>
> return $self;
> }
>
>
> package RocketLauncher;
> use strict;
> use base 'Weapon';
>
> sub new {
> my ( $self ) = @_;
> my $class = ref($self) || $self;
> $self = new Weapon();
>
> $self->{type} = 'ROCKET';
> $self->{hitpoints} = 100;
> return $self;
>
> }
>
> 1;
>
>
> --
> For this hour :
> Fools ignore complexity. Pragmatists suffer it. Some can avoid it.
> Geniuses remove it.
> Alan Perlis
Post Follow-up to this messageThens wrote:
> This is my attempt at a Perl code that does this. Is this the right
> way to do this. Any pointers will be of help.
There is a subtle mistake in your code. Have a look at the following
pods for more info on Perl's OO mechanisms:
perlboot
perltoot
perlobj
Also, if you're serious about using Perl's OO, then reading Damian
Conway's "Object Oriented Perl" is a must.
> #! /usr/local/bin/perl -w
>
> package Weapon;
>
> use strict;
>
> sub new {
> my ( $self ) = @_;
> my $class = ref($self) || $self;
> return bless { }, $class;
> }
>
> sub hitPoints {
> my ( $self ) = @_;
> return $self->{hitpoints};
> }
>
> sub fire {
> my ( $self, $target ) = @_;
> print "Destroyed the target !! ", $self->hitPoints;
> #$target->hurt($self->hitPoints);
> }
>
> package Gun;
> use strict;
> use base 'Weapon';
>
> sub new {
> my ( $self ) = @_;
> my $class = ref($self) || $self;
> $self = new Weapon();
Here, $self is an instance of the Weapon class. It is NOT a Gun object.
If you add the following:
print ref $self;
You will get Weapon, not Gun. Depending on your application, that could
not be a problem, but you're not getting true inheritance here. As long
as your Gun package does not have any distinct methods of its own (or
override any methods in Weapon, other than new()), then you are fine.
But if you require true inheritance, then you need to make $self an
instance of Gun. You do that by using SUPER:: like this:
$self = $class->SUPER::new;
This will look for the first new() method defined in the base class(es)
of Gun and will invoke it with $class as the parameter. So, it will call
the new() method in Weapon, which will return a hash ref blessed into
the Gun class.
> $self->{type} = 'GUN';
> $self->{hitpoints} = 10;
>
> return $self;
> }
Ditto for RocketLauncher.
--Ala
Post Follow-up to this messageAla Qumsieh <notvalid@email.com> wrote in comp.lang.perl.misc: > Thens wrote: > > > There is a subtle mistake in your code. Have a look at the following [snippage] > > Here, $self is an instance of the Weapon class. It is NOT a Gun object. Ah, I hadn't noticed when I certified this code as "free of gross errors" in another followup. This is a gross error in classes that do inheritance. Anno
Post Follow-up to this message*** post for FREE via your newsreader at post.newsfeed.com ***
Thens> sub new {
Thens> my ( $self ) = @_;
Thens> my $class = ref($self) || $self;
Thens> return bless { }, $class;
Thens> }
Please see <http://www.stonehenge.com/merlyn/UnixReview/col52.html>
about why that ref($self) thing is bad.
--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training
!
-----= Posted via Newsfeed.Com, Uncensored Usenet News =-----
http://www.newsfeed.com - The #1 Newsgroup Service in the World!
-----== 100,000 Groups! - 19 Servers! - Unlimited Download! =-----
Post Follow-up to this messagemerlyn@stonehenge.com (Randal L. Schwartz) wrote:
>
> Thens> sub new {
> Thens> my ( $self ) = @_;
> Thens> my $class = ref($self) || $self;
> Thens> return bless { }, $class;
> Thens> }
>
> Please see <http://www.stonehenge.com/merlyn/UnixReview/col52.html>
> about why that ref($self) thing is bad.
You recommend not using ref($self) because some people might guess
incorrectly what new() does when it is used as an instance method.
How about this: If people guess method behaviour rather than
reading the docs their votes don't count. Allow $object->new(),
document the behaviour, and expect people to read it.
Peter
--
#!/local/bin/perl5 -wp -*- mode: cperl; coding: iso-8859-1; -*-
# matlab comment stripper (strips comments from Matlab m-files)
s/^((?:(?:[])}\w.]'+|[^'%])+|'[^'\n]*(?:''[^'\n]*)*')*).*/$1/x;
Post Follow-up to this messagePeter J. Acklam <pjacklam@online.no> wrote in comp.lang.perl.misc: > merlyn@stonehenge.com (Randal L. Schwartz) wrote: > > > You recommend not using ref($self) because some people might guess > incorrectly what new() does when it is used as an instance method. > > How about this: If people guess method behaviour rather than > reading the docs their votes don't count. Allow $object->new(), > document the behaviour, and expect people to read it. The point isn't so much that people fail to look up the definition, but that they (specifically, readers of code that uses the class) are forced to look it up. When you know what "Class->new(...)" does, you also know what "ref( $obj)->new(...)" does, but for the meaning of "$obj->new(...)" you must go to the documentation. The shortcut of calling ->new as an object method is inherently unclear. Unless there are massive advantages in allowing it (there aren't in most classes), I think it is better to leave it out. Its use as a matter of course smacks of cargo cult. Anno
Post Follow-up to this messageThens <thens@NOSPAMti.com> wrote in message news:<20040906175436.32d95abf@asiclindt001>...[
color=darkred]
> I have a base class called as Weapon and I have derived classes 'Gun'
> and 'RocketLauncher'. I need to instantiate Gun or RocketLauncher
> based on a parameter say distance from the target. If the distance is
> less than 20m I need a gun and if it is more I will need a
> RocketLauncher.
>
> This is my attempt at a Perl code that does this. Is this the right
> way to do this. Any pointers will be of help.
>[/color]
I added some comments and code to your code. There was a problem with
the new methods in your child classes, they would have actually
returned you the wrong class type. All of the new methods would have
given you plain Weapon objects.
You don't show any code about how to create a class depending on the
conditions of distance as your statements above led me to belive the
code would try to do. Was your question more along the lines of "Did
I create me classes properly to use inheritance?"
Or pehaps you were trying to find out how to have a class
automatically change its type in the fire method? So when you invoke
fire it checks the target distance and then calls fire on the proper
weapon. Here is a class below
which will act like a weapon, but delegate out to other weapons in the
fire
method depending on the distance.
package SmartWeapon;
use strict;
use base 'Weapon';
sub new {
my $self = Weapon::new(@_);
$self->{rocket} = RocketLauncher->new();
$self->{gun} = Gun->new();
}
sub fire {
my ($self, $target) = @_;
if ($target->getDistance() < 20) {
$self->{gun}->fire($target);
}
else {
$self->{rocket}->fire($target);
}
}
> #! /usr/local/bin/perl -w
>
> package Weapon;
>
> use strict;
>
> sub new {
> my ( $self ) = @_;
> my $class = ref($self) || $self;
> return bless { }, $class;
> }
>
> sub hitPoints {
> my ( $self ) = @_;
> return $self->{hitpoints};
> }
>
> sub fire {
> my ( $self, $target ) = @_;
> print "Destroyed the target !! ", $self->hitPoints;
> #$target->hurt($self->hitPoints);
> }
>
> package Gun;
> use strict;
> use base 'Weapon';
>
> sub new {
# you could allow your parent class to intialize everything
# it needs to like this.
my $self = Weapon::new(@_);
# Don't need this stuff
> # my ( $self ) = @_;
> # my $class = ref($self) || $self;
> # $self = new Weapon();
>
# now you can initialize the variables needed for the child class
> $self->{type} = 'GUN';
> $self->{hitpoints} = 10;
>
> return $self;
> }
>
>
> package RocketLauncher;
> use strict;
> use base 'Weapon';
>
> sub new {
my $self = Weapon::new(@_);
# don't need this stuff
> #my ( $self ) = @_;
> #my $class = ref($self) || $self;
> #$self = new Weapon();
>
> $self->{type} = 'ROCKET';
> $self->{hitpoints} = 100;
> return $self;
>
> }
>
> 1;
Post Follow-up to this messageanno4000@lublin.zrz.tu-berlin.de (Anno Siegel) wrote:
> The shortcut of calling ->new as an object method is
> inherently unclear. Unless there are massive advantages
> in allowing it (there aren't in most classes), I think it
> is better to leave it out. Its use as a matter of course
> smacks of cargo cult.
The "$class = ref($obj) || $obj;" construction is used many
places in the Perl docs and the Perl standard modules, so
its not strange that people choose to use it.
Anyway, if it's use is disallowed an appropriate error
message should be given. Maybe something like this:
sub new {
my $class = shift;
croak "new(): not an instance method" if ref $class;
..
}
Peter
Post Follow-up to this messagePeter J. Acklam <pjacklam@online.no> wrote in comp.lang.perl.misc: > anno4000@lublin.zrz.tu-berlin.de (Anno Siegel) wrote: > > > The "$class = ref($obj) || $obj;" construction is used many > places in the Perl docs and the Perl standard modules, so Yes. Much to the regret of some of us. It's a pretty idiom, and it has been propagated by well-renowned people. (I'm tempted to say, people who should know better :) > its not strange that people choose to use it. No, it isn't. It is one of the harder design decisions *not* to do something on behalf of the user that seems to offer itself. If it is easy to do, and can as well be done outside the routine, think twice before doing it inside (and forcing it upon the user). You wouldn't sort a list result just because some users may want it sorted and others won't care. In this case, the performance penalty is obvious, so experienced programmers won't do it. The divantage of making ->new object-callable is "only" that the reader can't guess what exactly the object call does. That's less visible drawback, and so the idiom had a chance to spread. > Anyway, if it's use is disallowed an appropriate error > message should be given. Maybe something like this: > > sub new { > my $class = shift; > croak "new(): not an instance method" if ref $class; > ... > } Perhaps, but only because users may have come to expect it to be callable that way. Basically, ->new is a class method and the user has no business calling it through an object. If they do, they may as well deal with the consequences. Anno
Post Follow-up to this message
Show a Printable Version
Email This Page to Someone!
Receive updates to this thread
Powered by vBulletin
Copyright 2000-2006 Jelsoft Enterprises Limited.