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

-NB- before I start I must mention I'm an OO virgin so please take it slow.

I wrote this small module for a project I'm working on. It's supposed to build an array_ref [] into which I can add many instances of a hash_ref { code, index_value ) from this I would like to be able to sort the array via the index value and when the time comes print the whole list of 'code' in order.

I think I have achieved this minus safeguards etc. (check code below) but... when I add iXML::TheConstruct->new(); to my application it tells me that it "cant locate object method 'new' via package iXML::TheConstruct". I have used 'use lib "/dir/to/project"' and I have use iXML::TheConstruct; and the .pm is iXML/TheConstruct.pm and seems to be found ok.

Is it something to do with the way I have constructed my module, etc? I have look/searched everywhere including past nodes here but I cannot find an answer.

<sidenote> I'm also using Apache::Request, could that be having any adverse effects (I know it does with variables "not remaining shared")</sidenote>

iXML/TheConstruct.pm ->
#!/usr/bin/perl -w package iXML::TheConstuct; $VERSION = 0.01; use strict; sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = []; bless($self, $class); return $class; } sub add { my ($_self, $_obj_html, $_ind) = @_; my $_obj_hash = { OBJ_HTML => $_obj_html, OBJ_IND => $_ind}; push @{$_self}, $_obj_hash; # sort array according to hash OBJ_IND :) } sub output { my ($_self) = @_; my $_html_data; foreach my $_obj ( @{$_self} ) { $_html_data .= $_obj->{'OBJ_HTML'}; }; return $_html_data; } 1;

Replies are listed 'Best First'.
Re: Help: Constructors and all things OO.
by MZSanford (Curate) on Aug 28, 2001 at 16:48 UTC
    Ok, taking it slow ...

    The new() function should return the blessed object. It appears that return $class is returning the class, and not the object.
    The message you have ("cant locate object method 'new' via package iXML::TheConstruct") appears to have something to do with the way the new method is being called. from what you have, i am guessing it should be :
    use iXML::TheConstruct; use strict; my $obj = iXML::TheConstruct->new(); # ... get $html and $index $obj->add($html,$index); $output = $obj->output; #... do something with output.
    Does something like this work ? If a use lib '' is needed, that can be understood, but make sure you still have the use statement. I would also suggest using strict, warnings (or -w), and diagnotics on the test script to see if you can get any more information.
    can't sleep clowns will eat me
    -- MZSanford
      As above ++thanks. you where correct about returning the class instead of the blessed object.

      And yes I hope for it to work as you have stated above. I do have use strict; and -w (this is where I get the errors from).

      As far as I can see there are no problem or spelling mistakes at all. Apart from the obvious that is :)
        What i would suggest then, is wittling you code down into just what is needed to add one (hard coded) entry, and print the output (similar to the test code i used above). If this does not work, please post the code and output (messages i mean). If this does work, then start down the "what's diffrent ..." path. This is usually how every debugging sojourn starts.
        can't sleep clowns will eat me
        -- MZSanford
Re: Help: Constructors and all things OO.
by tachyon (Chancellor) on Aug 28, 2001 at 17:39 UTC

    This works OK. I've dropped in the sort for you to show you how you do it. $a and $b are the elements from the @array that we are sorting. In this case they are hash refs so we deref them to get the values we want to do our (numeric) sort on. You use 'cmp' rather than the spaceship '<=>' if you want a alphabetic sort. Note that reversing $a and $b reverses the sort order.

    #!/usr/bin/perl -w my $obj = iXML::TheConstruct->new(); # add some stuff for testing my $html = "A"; for $index( reverse 0..10) { $obj->add($html,$index); $html++; } # print it print "Here is our object\n", $obj->output; # do some sorts $obj->sort_asc; print "\n\nSort ascending\n", $obj->output; $obj->sort_dsc; print "\n\nSort descending\n", $obj->output; exit; ########### here is the module so we need no use ########### ############################################################ package iXML::TheConstruct; $VERSION = 0.01; use strict; sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = []; bless($self, $class); return $self; } sub add { my ($_self, $_obj_html, $_ind) = @_; my $_obj_hash = { OBJ_HTML => $_obj_html, OBJ_IND => $_ind}; push @{$_self}, $_obj_hash; } sub sort_asc { my $_self = shift || die "No object to sort!"; @$_self = sort { $a->{'OBJ_IND'} <=> $b->{'OBJ_IND'} } @$_self; } sub sort_dsc { my $_self = shift || die "No object to sort!"; @$_self = sort { $b->{'OBJ_IND'} <=> $a->{'OBJ_IND'} } @$_self; } sub output { my ($_self) = @_; my $_html_data; foreach my $_obj ( @{$_self} ) { my $index = $_obj->{'OBJ_IND'}; my $html = $_obj->{'OBJ_HTML'}; $_html_data .= "$index => $html\n"; } return $_html_data; } 1;

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

      Thats ++great tachyon... thanks heaps, I had read about the sort in another node on perlmonks but all the examples where using spaceships :) but hadn't tried to use anything I read yet (though I had it all bookmarked) but thanks heaps.

      As stated in one of my re:'s above, after more testing the problem seems to come when I try and load the module at the same time as Apache::Request; ( not the use itself but when I do "my $r = Apache->request" or "my $r = Apache::Request->new()" )

      I was thinking it might have something to do with the "use lib '';" statement. (I will add the site address to @INC another way and see if that makes any difference)

        See my Simple Module Tutorial for they whyfors and whatfors of @INC. In a nutshell your module must be in a directory specified in @INC. @INC usually contains these three directories:

        C:/Perl/lib 
        C:/Perl/site/lib 
        .

        This is a Windows example, just drop the C: for *nix. Now when you use "MyModule" Perl searches the @INC directories in order for "MyModule.pm". Note that the . dir is the current working directory of the script. There is a difference between module names and package names. If you have the line:

        use iXML::TheConstruct

        Then Perl will search for a module called "TheConstruct.pm" in a subdir called "iXML" in the @INC dirs. This is your problem. Using the module allows you to use the subs in the module by using the PACKAGE::SUB notation. Your package name could be package WhatsThatGotToDoWithThePriceOfFish;. You would then use iXML::TheConstruct; and instantiate your object via a call $obj = Whatsthatgottodowiththepriceoffish->new

        cheers

        tachyon

        s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

(arturo) Re: Help: Constructors and all things OO.
by arturo (Vicar) on Aug 28, 2001 at 16:42 UTC

    Assuming this is cut-and-pasted, I'd finger

    package iXML::TheConstuct;

    as the villain of the piece (note the missing "r").

      sorry I only c/p the module the rest I wrote in. my bad.
Re: Help: Constructors and all things OO.
by Hofmator (Curate) on Aug 28, 2001 at 16:47 UTC

    As a sidenote - are you sure you want to return $caller from your constructor, instead of the blessed object ($self)?

    -- Hofmator

      you where correct ++thanks but it wasn't the problem... because my other script (.pl) never even seems to find new();
Re: Help: Constructors and all things OO.
by Aighearach (Initiate) on Aug 28, 2001 at 16:45 UTC
    Looks like a typo in package iXML::TheConstuct, missing an r
    --
    Snazzy tagline here