Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Creating objects within objects being strange...

by Vuud (Novice)
on Sep 07, 2001 at 07:52 UTC ( [id://110823]=perlquestion: print w/replies, xml ) Need Help??

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

Larrys Name Be Praised...

I am having a strange strange strange problem with my bunch of objects.

I have TestScript that creates a SessionManager object. The SessionManager object, upon request creates a Session object. Keeps track of it and returns a sessionID upon success.

When I tell the SessionManager object to create the new session I make a call like so:

$retval = $sessionmanager->StartSession();

Inside the StartSession, if I do not pass a session ID, it creates a new session object. If I do a call to the Session package to make a new session object here like so:

my $session = new Session();

It works fine, my new routine in Session gets called.

If I change this so instead of making it here, it does a call like:

$sessid = $self->MakeNewSession();

and move the exact same call to create the new session down into here it stops working. the "my $session = new Session();" does not give an error (warnings are on). But any calls to functions of that object such as:

my $id = $session->SessionID();

Give me an error that says: Can't locate object method "SessionID" via package "main" at library/sessionmanager.pm line 155.

If I call $session->{'objectneedssave'} I can use it as a hash.

I also noticed that when I have warnings on, all of my bless statements give a warning that indicates my call to construct the object is not passing the class.

Could this be related?

HELP BEFORE I GO INSANE...

"I'm never going to work another day in my life. The Gods told me to relax... I'm gonna be hooked up right"

  • Comment on Creating objects within objects being strange...

Replies are listed 'Best First'.
Re: Creating objects within objects being strange...
by lachoy (Parson) on Sep 07, 2001 at 08:01 UTC
    Two things: First, you can always tell what package your object is actually blessed into with a ref $object. Second, check out perldoc -f bless. Instead of creating an object in your package you're creating it (somehow) in the 'main' package. Here's an example that replicates your problem:
    #!/usr/bin/perl use strict; my $main_object = bless( {} ); print "\$main_object is of type (", ref $main_object, ")\n"; $main_object->{blah} = 'blah'; $main_object->get_session();
    Running this gives me:
    Can't locate object method "get_session" via package "main" (perhaps you forgot to load "main"?) at bless_main.pl line 8. $main_object is of type (main)
    If you want to avoid surprises like this, always use the two-argument form of bless, like:
    my $object = bless( {}, 'My::Object' );
    Or more commonly:
    sub new { my ( $item ) = @_; my $class = ref $item || $item; return bless( {}, $class ); }
    Hope this helps.

    Chris
    M-x auto-bs-mode

      I was using the two arguement form... the only difference is that I was not doing an my $class= ref $item || $item;

      I was just taking the $class off the @_ first. The problem is that it is coming through undefined for some reason or another.

      Here is what I am using now:

      sub new {
              my $item = shift;
      	my @args = @_;
              my $self = {};
              my $class= ref $item || $item;
              print $class;
              bless($self, $class);
              $self->Session::init (@args);
              return $self;
      };
      

      The call I am making to it is like:

      my $sessionmanager = new SessionManager();

      Still $class is undefined.

      "I'm never going to work another day in my life. The Gods told me to relax... I'm gonna be hooked up right"

        Hi Vuud,

        Theres something here that I dont grok. more specifically the line:

        $self->Session::init (@args);
        Now maybe I have missed something, but I dont understand what the above is supposed to do. Session::init I presume is a subroutine in the Session package. So why are you calling it against $self? Since you havent told us what package the new is from its hard to tell what you are up to.

        I think you have some basic misunderstandings that would be cleared up by reading perltoot perlboot or perlobj. But ill try to give you an overview here.

        In perl you can call a method in two ways. The first is a hangover to make C++ types feel more cozy the other way is the correct way to do it.

        my $obj=new Some::Module; # ok but not so cool my $obj=Some::Module->new(); # TWTDI
        You can see how this differs to the above sample from your new(). Im not even going to try to figure out how perl is interpreting your statement up there, but I am virtually certain its not doing what you think its doing

        Anyway here is how I expected your new to look (and this is straight from perltoot)

        package Session; #.... sub new { my $proto=shift; my $class=ref($proto) || $proto; my $self=bless {}, $class; # the below line assumes that this new is from # the Session class $self->init(@_); #no need to copy @_ return $self; };
        Now from this point on all the help I can give is conjecture as your OP makes assumptions about what we know about things we have never seen (ie your code, and object model). Remember we havent been fighting/living/breathing this stuff for days so things that you take for granted we dont even know... :-) For instance what happens if you dont pass a Session ID to StartSession?

        Nevertheless here is what I think you might need,

        package SessionManager; #.... sub MakeNewSession { my $self=shift; my $session=Session->new() || die "Failed to construct Session!"; my $id=$session->SessionID; die "SessionID returned an undef value!" if !defined($id); print "New session has ID of ".$i; return $session; }
        So the above sub will create a new session object print out its id and return it. I hope I havent misunderstood your question/problem and that this helps

        Dont forget to read perltoot perlboot or perlobj. PerlToot and PerlBoot are very good tutorials and much about Perl let alone OOPerl can be learned from both.

        Yves
        --
        You are not ready to use symrefs unless you already know why they are bad. -- tadmc (CLPM)

      I should also note, that the Session package runs fine against my test file. Same call to it and everything.

      It tests all the functions and it runs clean - no warnings or anything.

      "I'm never going to work another day in my life. The Gods told me to relax... I'm gonna be hooked up right"

        Okay - after poking and proding it with various sticks, I have determined that when I call the new constructor in the session object, it is actually calling the new constructor in the SessionManager class.

        I cannot get it to point at the session object - no matter what I do, or syntax I use, it constantly goes at the new in the same object (as if I was doing $self->new).

        Its also not passing the class. The damn thing works fine from the test module!

        "I'm never going to work another day in my life. The Gods told me to relax... I'm gonna be hooked up right"

Re: Creating objects within objects being strange...
by mr.nick (Chaplain) on Sep 07, 2001 at 16:04 UTC
    This comment is unrelated to your question, but I thought I'd mention something quickly that I've picked up recently and found very useful.

    Consider writing your new functions something like this:

    sub new { my $proto=shift; my $class=ref $proto || $proto; my $self={ @_ }; ## ... bless $self,$class; }

    Then create your instance like this:

    my $inst=new MyClass( name => 'mr.nick', rank => 'novice', sleep_level => 'not enough' );
    I found that by directly putting the class parameters on the new() line like that makes for cleanliness, and readability. And, it makes for a real quick method of stuffing values into the instance of the object.

    mr.nick ...

      I would MUCH prefer to see the below.
      my $inst=MyClass->new( name => 'mr.nick', rank => 'novice', sleep_level => 'not enough' );
      The notation is easier to read, and less susceptable to errors. Also it is more intuitive. It is clear the function is called is 'new' and that new() resides in the class/package 'MyClass' and that 'MyClass' will be passed to new() as its first parameter, along with the parameters supplied.

      The other notation is much less clear. When I see a bareword followed by parameters in parenthesis my first thought is that it is a function being called. Which is as we all know NOT what is happening.

      BTW: This is one of my pet peeves, can you tell? :-)

      Yves
      --
      You are not ready to use symrefs unless you already know why they are bad. -- tadmc (CLPM)

        Heh, well, yes, you certainly aren't alone in your feeling about that ;) I guess me writing it as "new Object" instead of "Object->new()" is a leftover from my C++ days and from the fact that I (apparently) am a Java developer now :-/ (which, one of these days, I'm going to write a nice meditation on the comparitive differences between the two ... I have to admit, I like Java... it makes OO programming in perl seem very clunky).

        mr.nick ...

        Okay, I will change it - I see what you mean. It wont solve my problem though... and the classname is not being passed for some reason when I call it from within the damn routine.

        I hope to make a simple example I can post tonight and hopefully solve the (i assume) stupid mistake I am making

        Later

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://110823]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (3)
As of 2024-04-24 02:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found