modifying @ISA

Discussion in 'Perl Misc' started by Gibbering Poster, Aug 6, 2004.

  1. Hey .. i'm playing around with the silly idea (yah I know) of writing a
    roguelike in Perl, and had a quick question about dynamic multiple
    inheritance.

    I have a main IO Handler object called Handler. When the game is started,
    it checks your OS, and returns you an object of class Handler::Win or
    Handler::Linux depending on what $^O contains. So far, so good.

    The main Handler super-object contains methods to return objects like
    player, map, etc for the child handler, so he can know how to paint the
    screen and such.

    I've decided that I'd like to be able to subclass the handler on levels
    other than the OS. I'd like to have:

    Handler::DungeonMovement
    Handler::playerCreation
    Handler::Inventory
    Handler::prompt
    etc....

    What I was thinking I would do is morph the object as I needed to change the
    handler object. For instance, When the game starts, the win32 handler adds
    Handler::playerCreation to its @ISA list so that one can choose
    name/class/etc ... Once that's complete, I was hoping I could remove
    Handler::playerCreation from the @ISA list, and push on
    Handler::DungeonMovement so that the process_key method would know how to
    properly interprate the keystrokes to move the player around the dungeon.

    I'm having a tough time dynamically modifying the Handler::Win32's @ISA list
    for a blessed object instance...

    Here's some code that demonstrates a constuctor for the main super Handler
    class that will create the proper OS handler, then TRY to immediatly throw
    them into 'movement' mode, by trying to twiddle @ISA:

    sub new ($$) {
    my ($handler, $mode) = @_;

    if ($^O =~ /win/i) {
    $handler = Handler::Win -> new;
    } else {
    $handler = Handler::Unix -> new;
    }
    if ($mode eq 'movement') {
    push @$handler::ISA => 'Movement';
    }
    return $handler;
    }

    I KNOW that push line is ridiculously wrong syntactically, but I wanted to
    give you an idea of what I was trying to do...
    What's the proper syntax to do this, and is the whole architecture lame?

    Thanks VERY much in advance for help :)
     
    Gibbering Poster, Aug 6, 2004
    #1
    1. Advertising

  2. Gibbering Poster wrote:

    > Hey .. i'm playing around with the silly idea (yah I know) of writing a
    > roguelike in Perl, and had a quick question about dynamic multiple
    > inheritance.
    >
    > I have a main IO Handler object called Handler. When the game is started,
    > it checks your OS, and returns you an object of class Handler::Win or
    > Handler::Linux depending on what $^O contains. So far, so good.


    No, but I'll explain why later.

    > The main Handler super-object contains methods to return objects like
    > player, map, etc for the child handler, so he can know how to paint the
    > screen and such.
    >
    > I've decided that I'd like to be able to subclass the handler on levels
    > other than the OS. I'd like to have:
    >
    > Handler::DungeonMovement
    > Handler::playerCreation
    > Handler::Inventory
    > Handler::prompt
    > etc....
    >
    > What I was thinking I would do is morph the object as I needed to change the
    > handler object. For instance, When the game starts, the win32 handler adds
    > Handler::playerCreation to its @ISA list so that one can choose


    No, you have got the wrong end of the stick.

    @ISA describes (static) interhitance relationships between _classes_ not
    _objects_. You should mess with it like this. If you have an object
    that wants to morph from one class into a one of it's child classes you
    can simply re-bless it although this can mke for rather incoprehensible
    code.

    In fact the only time you would usually have anything other than a
    totally static @ISA is in cases like of your Handler::Linux and
    Handler::Win32 as the OS is not going to change withing the lifetime of
    the process.

    Your basic Handler object should simply be of class Handler. Subclasses
    should inherit from that.

    i.e.

    @Handler::DungeonMovement::ISA = qw( Handler );
    # etc...

    but the classes Handler::Linux and Handler::Win32 are not decendants of
    Handler in the class hierachy - they are alternate parents!

    > Here's some code that demonstrates a constuctor for the main super Handler
    > class that will create the proper OS handler, then TRY to immediatly throw
    > them into 'movement' mode, by trying to twiddle @ISA:
    >
    > sub new ($$) {


    Constructors in Perl are conventionaly called as class methods. Methods
    don't have prototypes in Perl.

    > my ($handler, $mode) = @_;
    >
    > if ($^O =~ /win/i) {
    > $handler = Handler::Win -> new;
    > } else {
    > $handler = Handler::Unix -> new;
    > }
    > if ($mode eq 'movement') {
    > push @$handler::ISA => 'Movement';
    > }
    > return $handler;
    > }
    >
    > I KNOW that push line is ridiculously wrong syntactically,


    The syntax is not nearly as ridiculous as the semantics.

    The Handler class should tune it's @ISA at compile time.

    package Handler;
    BEGIN {
    if ($^O =~ /win/i) {
    # May want to require Handler::Win;
    @ISA = qw ( Handler::Win );
    } else {
    # May want to require Handler::Unix;
    $handler = Handler::Unix -> new;
    }
    }

    sub os_specific_init {
    # Nothing!
    }

    sub new {
    my $class = shift;
    my $self = bless {}, $class;
    $self->os_specific_init;
    $self;
    }


    package Handler::Win;

    sub os_specific_init {
    my $self = shift;
    # Do windows specific bit.
    }

    Or somesuch approach. As ever TIMTOWTDI.

    Do not pass $mode as an argument to Handle->new.

    Instead just call Handler::DungeonMovement->new.

    This method call will in fact resolve as subroutine call
    Handle::new('Handler::DungeonMovement') which will construct a
    Handler::DungeonMovement object.
     
    Brian McCauley, Aug 6, 2004
    #2
    1. Advertising

  3. Gibbering Poster

    Joe Smith Guest

    Gibbering Poster wrote:

    > Once that's complete, I was hoping I could remove
    > Handler::playerCreation from the @ISA list, and push on
    > Handler::DungeonMovement so that the process_key method would know how to
    > properly interprate the keystrokes to move the player around the dungeon.


    That does not make sense, unless you are using code like:
    $key = get_keystroke();
    $handle->a() if $key eq 'a';
    $handle->b() if $key eq 'b';
    $handle->c() if $key eq 'c';

    Diddling with @ISA is not the way to handle dispatch tables.

    Create a hash with coderefs for each legal letter in PlayerCreation mode.
    This will be used to map letters to subroutines.
    Create another hash with coderefs for DungeonMovement mode.
    Set your command loop to use one or the other depending on which mode
    you're in. The selected hash can be used to determine which command
    letters are legal in this mode, and which subroutine to invoke when
    a legal letter is seen.

    You could push and pop hash references onto an array to have stacked
    dictionaries (like Postscript uses).

    @dispatch = \%Help; # These commands are legal everywhere
    push @dispatch, \%Create;
    ... # acceptable commands = union of Create + Help;
    pop @dispatch;
    push @dispatch, \%Movement;
    ... # Move around
    push @dispatch, \%Inventory
    ... # acceptable commands = union of Inventory + Movement + Help
    pop @dispatch;
    ... # acceptable commands = union of Movement + Help
    pop @dispatch;

    sub process_keystroke {
    my $self = shift;
    my $key = shift;
    for my $n (1 .. @dispatch) {
    my $href = $dispatch[-$n]; # Traverse from end to front
    if (defined $href->{$key}) {
    return $href->{$key}($self); # Invoke appropriate function
    }
    }
    return unknown_command($self,$key);
    }

    -Joe
     
    Joe Smith, Aug 7, 2004
    #3
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. sandy
    Replies:
    2
    Views:
    550
    sandy
    Apr 26, 2004
  2. =?Utf-8?B?YnVr?=

    ASP.NET Viewstate & ISA Server 2004

    =?Utf-8?B?YnVr?=, Aug 18, 2005, in forum: ASP .Net
    Replies:
    0
    Views:
    447
    =?Utf-8?B?YnVr?=
    Aug 18, 2005
  3. Jim in Arizona

    ISA 2000 Administration

    Jim in Arizona, Apr 24, 2006, in forum: ASP .Net
    Replies:
    0
    Views:
    364
    Jim in Arizona
    Apr 24, 2006
  4. c45aed
    Replies:
    0
    Views:
    442
    c45aed
    Feb 16, 2004
  5. C Gillespie

    Using isA and getA in a python way

    C Gillespie, Sep 20, 2004, in forum: Python
    Replies:
    4
    Views:
    510
    Jeremy Bowers
    Sep 20, 2004
Loading...

Share This Page