Object References as a member of a bigger Object


O

O. Olson

Hi,

I am practicing a bit of Perl and I have hit on to a problem. I am
more into C++/Java - so I am not confident about my Perl lingo.

I have two classes MyTime and ScheduleTask - each in packages.
ScheduleTask has two fields that should reference MyTime objects.

My problem is that in the as_text() SubRoutine of ScheduleTask I
cannot seem to be able to get the as_textTime() SubRoutine of the
MyTime objects. It tells me "Can't call method "as_textTime" without a
package or object reference ... "

Following are pieces of my Code: (I hope I got everything here)

---------------------------------------------------------
main.pl
---------------------------------------------------------
use warnings;
use strict;
use MyTime;
use ScheduleTask;
use String::Scanf;

my $str = "04:00:00 to 04:59:00 Do_Something";
my $schedule_task = new ScheduleTask();
$schedule_task->parseTask($str);
print $schedule_task->as_text . "\n"; # Here's the problem !!!

---------------------------------------------------------
ScheduleTask.pm
---------------------------------------------------------
package ScheduleTask;

use warnings;
use strict;
use String::Scanf;
use MyTime;

sub new {
my $inv = shift;
my $class = ref( $inv ) || $inv;
die "The SubRoutine new() cannot be called with any arguments\n"
unless @_ ==0;
my $self;

# For a new object the fields would be undefined
$self = {
START_TIME => undef,
STOP_TIME => undef,
NAME => undef
};

return bless $self, $class;
}


# Takes a string of the form "%02d:%02d:%02d to %02d:%02d:%02d %s" and
extracts the Task
sub parseTask {
my $task = $_[0]; # Get the Task Object passed
my $line = $_[1]; # Get the string
print "Line = $line \n";

my ($start_time_str, $stop_time_str, $name_str) =
String::Scanf::sscanf("%s to %s %s", $line);

my $start_time = new MyTime()->parseTime($start_time_str);
my $stop_time = new MyTime()->parseTime($stop_time_str);

# Finally collect all the above data together
($task->{START_TIME}, $task->{STOP_TIME}, $task->{NAME}) =
($start_time, $stop_time, $name_str);

#print as_text() . "\n"; # This does not seem to work
}


sub as_text {
my $self = shift; # Get the object
my $start_time = $self->{START_TIME};
my $stop_time = $self->{STOP_TIME};
return $start_time->as_textTime . " to " . $stop_time-
as_textTime . " " . $self->{NAME};

}
1;

---------------------------------------------------------
MyTime.pm
---------------------------------------------------------
package MyTime;

use warnings;
use strict;
use String::Scanf;

sub new {
my $inv = shift;
my $class = ref( $inv ) || $inv;
die "Too many arguments\n" unless @_ <=3;
my $self;

if ( @_ == 0 ) {

my @time = localtime( );
$self = { HOUR => $time[ 2 ],
MINUTE => $time[ 1 ],
SECOND => $time[ 0 ] };
} else {
$self = { HOUR => $_[ 0 ],
MINUTE => $_[ 1 ] || 0,
SECOND => $_[ 2 ] || 0 };
}

return bless $self, $class;
}

# Takes a string of the form "%02d:%02d:%02d" and extracts the Time
sub parseTime {
my $time = $_[0]; # Get the Time object passed
my $line = $_[1]; # Get the string
print "Line = $line \n";

($time->{HOUR}, $time->{MINUTE}, $time->{SECOND}) =
String::Scanf::sscanf("%02d:%02d:%02d", $line);

print "Parsed Time:" . $time->as_text . "\n";
}

sub as_textTime {
my $self = shift;
return sprintf "%02d:%02d:%02d",
$self->{ HOUR }, $self->{ MINUTE }, $self-
{ SECOND };

}
1;
---------------------------------------------------------

I am sorry for this long post - but I needed to post sufficient code
to reproduce my problem.
Thanks a lot,
O.O.
 
Ad

Advertisements

A

anno4000

O. Olson said:
Hi,

I am practicing a bit of Perl and I have hit on to a problem. I am
more into C++/Java - so I am not confident about my Perl lingo.

I have two classes MyTime and ScheduleTask - each in packages.
ScheduleTask has two fields that should reference MyTime objects.

My problem is that in the as_text() SubRoutine of ScheduleTask I
cannot seem to be able to get the as_textTime() SubRoutine of the
MyTime objects. It tells me "Can't call method "as_textTime" without a
package or object reference ... "

Following are pieces of my Code: (I hope I got everything here)

Matt Madrid has pointed out one error: The parseTask method doesn't
return an object ($task) but the return value of a print statement (1).

I have annotated some more. I don't see how your code could even
have reached the statement that you claim showed the error.
---------------------------------------------------------
main.pl
---------------------------------------------------------
use warnings;
use strict;
use MyTime;
use ScheduleTask;
use String::Scanf;

my $str = "04:00:00 to 04:59:00 Do_Something";
my $schedule_task = new ScheduleTask();
$schedule_task->parseTask($str);
print $schedule_task->as_text . "\n"; # Here's the problem !!!

---------------------------------------------------------
ScheduleTask.pm
---------------------------------------------------------
package ScheduleTask;

use warnings;
use strict;
use String::Scanf;
use MyTime;

sub new {
my $inv = shift;
my $class = ref( $inv ) || $inv;
die "The SubRoutine new() cannot be called with any arguments\n"
unless @_ ==0;
my $self;

# For a new object the fields would be undefined
$self = {
START_TIME => undef,
STOP_TIME => undef,
NAME => undef
};

return bless $self, $class;
}


# Takes a string of the form "%02d:%02d:%02d to %02d:%02d:%02d %s" and
extracts the Task
sub parseTask {
my $task = $_[0]; # Get the Task Object passed
my $line = $_[1]; # Get the string
print "Line = $line \n";

my ($start_time_str, $stop_time_str, $name_str) =
String::Scanf::sscanf("%s to %s %s", $line);

I don't have the module String::Scanf. The split function can replace
it here:

my ($start_time_str, undef, $stop_time_str, $name_str) =
split ' ', $name_str;
my $start_time = new MyTime()->parseTime($start_time_str);
my $stop_time = new MyTime()->parseTime($stop_time_str);

That won't do. It tries to call ScheduleTask::MyTime which doesn't
exist.

My $start_time = MyTime->new->parseTime($start_time_str);

should come closer.
# Finally collect all the above data together
($task->{START_TIME}, $task->{STOP_TIME}, $task->{NAME}) =
($start_time, $stop_time, $name_str);

#print as_text() . "\n"; # This does not seem to work
}


sub as_text {
my $self = shift; # Get the object
my $start_time = $self->{START_TIME};
my $stop_time = $self->{STOP_TIME};
return $start_time->as_textTime . " to " . $stop_time-
as_textTime . " " . $self->{NAME};

}
1;

---------------------------------------------------------
MyTime.pm
---------------------------------------------------------
package MyTime;

use warnings;
use strict;
use String::Scanf;

sub new {
my $inv = shift;
my $class = ref( $inv ) || $inv;
die "Too many arguments\n" unless @_ <=3;
my $self;

if ( @_ == 0 ) {

my @time = localtime( );
$self = { HOUR => $time[ 2 ],
MINUTE => $time[ 1 ],
SECOND => $time[ 0 ] };
} else {
$self = { HOUR => $_[ 0 ],
MINUTE => $_[ 1 ] || 0,
SECOND => $_[ 2 ] || 0 };
}

return bless $self, $class;
}

# Takes a string of the form "%02d:%02d:%02d" and extracts the Time
sub parseTime {
my $time = $_[0]; # Get the Time object passed
my $line = $_[1]; # Get the string
print "Line = $line \n";

($time->{HOUR}, $time->{MINUTE}, $time->{SECOND}) =
String::Scanf::sscanf("%02d:%02d:%02d", $line);

Again, split can do the job:

@time{ qw( HOUR MINUTE SECOND)} = split /:/, $line;
print "Parsed Time:" . $time->as_text . "\n";
}

The method as_text() doesn't exist in package MyTime. It should be
as_textTime.
sub as_textTime {
my $self = shift;
return sprintf "%02d:%02d:%02d",
$self->{ HOUR }, $self->{ MINUTE }, $self-

}
1;

Anno
 
O

O. Olson

Thanks Matt.

$start_time will be whatever the return value from MyTime::parseTime() is,
not an object. Looking at the code in MyTime::parseTime(), that return value
will be the return value from the final print statement.

I actually thought that a new object would be created with new() and
then parseTime() would be called to update that new object. That is
why I did not have parseTime() return anything.
Now, $task->{START_TIME} is equal to 1.

Now, when I have included a return statement in parseTime() it seems
to work.

Thanks a lot,
O.O.
 
Ad

Advertisements

O

O. Olson

Thanks Anno for replying again.

Matt Madrid has pointed out one error: The parseTask method doesn't
return an object ($task) but the return value of a print statement (1).

I have annotated some more. I don't see how your code could even
have reached the statement that you claim showed the error.

Yes, you are right. I actually had as_text() and as_textTime() doing
the same thing in the package MyTime. I forgot to change that.

I don't have the module String::Scanf. The split function can replace
it here:

my ($start_time_str, undef, $stop_time_str, $name_str) =
split ' ', $name_str;


Thanks for pointing this out. I would like to learn the Perl way of
doing things here.

That won't do. It tries to call ScheduleTask::MyTime which doesn't
exist.

My $start_time = MyTime->new->parseTime($start_time_str);

should come closer.

I tried to replace the following in my original code.

#my $start_time = MyTime->new()->parseTime($start_time_str);
#my $stop_time = MyTime->new()->parseTime($stop_time_str);

my $start_time = MyTime->new();
my $stop_time = MyTime->new();

$start_time->parseTime($start_time_str);
$stop_time->parseTime($stop_time_str);


This replacement works i.e. I get the expected output even when
parseTime() does not return anything as my original code posted. So
does this mean, that what is above is not equivalent to what is below.
I thought we could nest these functions calls.


Thanks again,
O.O.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top