yoda54 has asked for the wisdom of the Perl Monks concerning the following question:

Greetings Monks! I seek your enlightenment. How do I make objects interact with each other? For instance, lets say I have one object attack another object? How do I change an objects internal data?
#!/usr/bin/perl use strict; use warnings; use Peasant; my $henry = Peasant->new(name => "Peasant1", hp => "15"); my $joe = Peasant->new(name => "Peasant2", hp => "15"); $joe->damage($henry->attack); $henry->damage($joe->attack);
package Peasant; use strict; sub new { my ($class, %arg) = @_; my $objref = { _name => $arg{name} || "unknown", _hp => $arg{name} || "unknown" }; bless $objref, $class; return $objref; } sub damage { print "$_[0] damage\n"; $_[0]->{_hp} - $_[0]; } sub name { return $_[0]->{_name} } sub attack { my $int = int(rand(5)); print "$_[0]->{_name} attacks for $int.....\n"; return $int; } 1;

Replies are listed 'Best First'.
Re: Perl OO newbie advice - object interaction
by GrandFather (Saint) on Jun 21, 2006 at 05:10 UTC

    A number of bugs in there. First, you need to fix the code for initialising hit points in your constructor:

    _hp => $arg{hp} || rand (10) + 2

    These are objects. You get your blessed object as the first parameter when a sub is called against an object so:

    sub damage { my ($self, $hits) = @_;

    and you can use the object ref to acces the object data:

    $self->{_hp} - $hits;

    Taken all together your code ends up like:

    use strict; use warnings; package Peasant; use strict; sub new { my ($class, %arg) = @_; my $objref = { _name => $arg{name} || "unknown", _hp => $arg{hp} || rand (10) + 2 }; bless $objref, $class; return $objref; } sub damage { my ($self, $hits) = @_; print "$hits damage\n"; $self->{_hp} - $hits; } sub name {return shift->{_name}; } sub attack { my $self = shift; my $int = int(rand(5)); print "$self->{_name} attacks for $int.....\n"; return $int; } 1; package main; my $henry = Peasant->new(name => "Henry", hp => "15"); my $joe = Peasant->new(name => "Joe", hp => "15"); $joe->damage($henry->attack ()); $henry->damage($joe->attack ());

    which prints:

    Henry attacks for 1..... 1 damage Joe attacks for 1..... 1 damage

    DWIM is Perl's answer to Gödel
      I think you're forgetting that the damage() method has to actually alter the object's hit-points:
      sub damage { ... $self->{_hp} = $self->{_hp} - $hits; # or, more succinctly: # $self->{_hp} -= $hits; }

      Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
      How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
Re: Perl OO newbie advice - object interaction
by jhourcle (Prior) on Jun 21, 2006 at 14:47 UTC
    Greetings Monks! I seek your enlightenment. How do I make objects interact with each other? For instance, lets say I have one object attack another object? How do I change an objects internal data?

    From years of mudding, I'd probably abstract out a little more. Instead of:

    $joe->damage($henry->attack); $henry->damage($joe->attack);

    I'd use something more like

    $henry->attack($joe); $joe->attack($henry); sub attack { my ($self,$target) = @_; ... # compare dex/abilities to see if you hit the target if ( $hit ) { ... # compute damage from the attack $target->damage( $amount, $self ); ... # emit messages about the attack } else { ... # emit messages about a miss } } sub damage { my ($self, $amount, $attacker) = @_; ... # adjust amount for armour, etc. $self->{_hp} -= $amount; # this assumes the object is a hashref # this may not be the case ... see 'perldoc perltoot' if ( $self->{_hp} <= 0 ) { ... # whatever to do for death } }

    Of course, I'd personally use some existing mud base (eg, PerlMUD if you're going to do it in perl ... (although I've never used it ... most of my mud coding was in LPC)), an then modify it to suit my needs. (c'mon ... damage in hp only? if you pass a type of damage, you can account for armour differences and/or resistances/weaknesses)

Re: Perl OO newbie advice - object interaction
by perl_lover (Chaplain) on Jun 21, 2006 at 05:05 UTC
    Internal data you can edit directly. An Object in perl is internally a hash. $object->{_member} will give you the value. Perl doesn't support data hiding as it is not a pure Object Oriented Language. But you can still aviod this kind of attach by using InsideOut Object

    Inside Out Object

    -perl_lover-
      Howdy!

      Internal data you can edit directly. An Object in perl is internally a hash. $object->{_member} will give you the value. Perl doesn't support data hiding as it is not a pure Object Oriented Language. But you can still aviod this kind of attach by using InsideOut Object
      That collection of statements contains the barest shreds of truth.

      Perl objects do not have a defined form. Blessed hashes are merely the most frequently used form, but the only thing consistent about objects in Perl is that they are blessed references. The reference might well lead you nowhere (as in Inside Out Objects).

      Data hiding is quite possible, but you need to do something other than blessed hashes. Inside Out Objects permit data to be hidden such that nothing outside the defining package can touch it directly. In fact, you can even set tighter bounds on it, such that the state can only be accessed through methods, even within the package.

      I recommend Conway, Object Oriented Perl, as a fairly comprehensive look at the different ways you can do OO in Perl. It can expand your horizons tremendously.

      yours,
      Michael