package Student; use strict; use warnings; use Carp; my $total = 0; #total number of students our $DEBUG = 0; #print debugging info if true use overload '""' => \&string; #constructor. Student will be passed a name and RIN. GPA set to 0. sub create { $total ++; my $class = shift; carp "Student name and/or RIN not passed, using undef" unless @_ == 2; my ($name, $RIN) = @_; my $obj = { name=>$name, RIN=>$RIN, GPA=>0 }; print "Added $name, with RIN: $RIN\n" if $DEBUG; bless $obj, $class; } #name accessor. If an argument is passed, sets the name. Returns the #name either way sub name{ my $obj = shift; $obj->{name} = $_[0] if @_; return $obj->{name}; } #RIN and GPA accessors are almost identical to name() above, so we'll add some error checking sub RIN{ my $obj = shift; if (@_){ carp "RIN doesn't look like a RIN" if $_[0] !~ /^\d{3}-?\d{2}-?\d{4}$/; $obj->{RIN} = $_[0]; } return $obj->{RIN}; } sub GPA{ my $obj = shift; if (@_){ my ($GPA) = @_; if ($GPA !~ /^\d+(\.\d+)?$/){ carp "GPA is non-numeric, using 0"; $GPA = 0; } $obj->{GPA} = $GPA; } return $obj->{GPA}; } #Report whether student is passing or failing sub status { my $obj = shift; $obj->{GPA} >= 60 ? 'passing' : 'failing'; } #overloaded stringification sub string { my $obj = shift; "$obj->{name} ($obj->{RIN})"; } #Destructor sub DESTROY { my $obj = shift; $total--; print "$obj->{name} about to fall out of scope\n" if $DEBUG; } #report how many students we have sub students { $total; } 1; #surprisingly important statement!!