Re: oop, variable that counts the number of objects created
by choroba (Cardinal) on Jul 30, 2020 at 07:25 UTC
|
You can create a lexical variable in the class that gets incremented in the constructor and decremented in the destructor. A class closure method makes this value accessible from outside. Don't forget to call SUPER::new in child classes.
#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
{ package Car;
my $count;
sub new {
my ($class, $name, $price) = @_;
my $self = {name => $name,
price => $price,
speed => 0};
say 'Object car being created:';
say "Name: $name";
say "Price: $price\n";
++$count;
return bless $self, $class
}
sub speed_up {
my ($self, $acc) = @_;
return $self->{speed} += $acc
}
sub slow_down {
my ($self, $acc) = @_;
return $self->{speed} -= $acc
}
sub DESTROY {
say 'Scrap!';
--$count
}
sub count {
return $count
}
}
{ package Car::GeneralMotors::Firebird;
use parent -norequire => 'Car';
sub new {
my ($class, $price) = @_;
$class->SUPER::new('General Motors Firebird', $price);
}
}
my @cars;
for (1 .. 10) {
push @cars, 'Car'->new('Peel P50', 176_000);
}
splice @cars, 0, 5;
say 'Car'->count;
say 'It works for subclasses, too:';
my $f = 'Car::GeneralMotors::Firebird'->new(200_000);
say 'Car'->count;
undef $f;
say 'Car'->count;
map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
| [reply] [Watch: Dir/Any] |
Re: oop, variable that counts the number of objects created
by tobyink (Canon) on Jul 30, 2020 at 09:40 UTC
|
use Zydeco prefix => 'App';
class Car {
has name ( type => Str );
has price ( type => Num );
has speed (
type => Num,
default => 0,
handles_via => 'Number',
handles => {
speed_up => 'add',
slow_down => 'sub',
},
);
my $count;
method BUILD { ++$count }
method DEMOLISH { --$count }
method count { $count }
}
my $red_car = App->new_car( name => 'Red' );
my $blue_car = App->new_car( name => 'Blue' );
$red_car->speed_up( 25 );
$red_car->speed_up( 10 );
say $red_car->speed;
say App::Car->count;
| [reply] [Watch: Dir/Any] [d/l] |
|
not germane to OP but generally relevant
Nice to see this example. I should probably ask this in another thread, but what's the obsession with has? Can't we (everyone not just your modules) just have blocks all the way down or superficially support something that's familiar to JAVA programmers? At this point we're just cargo culting a failed declarative approach (IMO).
What are we getting beyond classic Perl OO? (sincerely want to break this down for the benefit of the overall discussion):
- protected methods
- strong types/checking
- strong data encapsulation
What else? If this has been hashed out before (a true breakdown), I'd be satisfied with a link. TY!
| [reply] [Watch: Dir/Any] [d/l] |
|
# Java
class Car {
public String name;
public int price;
public int speed;
}
# Zydeco
class Car {
has name ( type => Str );
has price ( type => Int );
has speed ( type => Int );
}
Where would you add blocks to the Zydeco example to make it more like Java?
| [reply] [Watch: Dir/Any] [d/l] |
|
|
|
Re: oop, variable that counts the number of objects created
by perlfan (Vicar) on Jul 30, 2020 at 03:35 UTC
|
my $auto = new car("Opel Vectra",50000);
Do:
my $auto = car->new("Opel Vectra",50000);
Create a container class that provides methods meant for groups of cars. Add a license plate (UUID) field to the Car class. You can even support sub classes of Car (package names should start with an upper case letter) using polymorphism.
Code not tested or fully complete but you get the gist. Note: it requires you pass it Car instances. You could get fancy and roll that up in it, but I wouldn't personally.
use strict;
use warnings;
package Garage;
sub new {
my $pkg = shift;
my $self = {
all_cars => {}, # store cars key'd by license plate (uuid)
}
blese $self, $pkg;
return $self;
}
sub add_car {
my ($self, $car) = $@;
#... add car key'ed by license plate or uuid
}
sub del_car {
my ($self, $uuid) = $@
delete $self->get_cars->{$uuid};
}
sub get_cars {
my $self = shift;
return $self->{all_cars};
}
sub get_car {
my ($self, $uuid) = $@;
my $cars = $self->get_cars;
die "Car with plate $uuid is not in the garage!\n\n" if not $cars->{
+$uuid}; # die can throw a reference also, so there you can do the exc
+eption thing in the caller
return $cars->{$uuid};
}
sub count_cars {
my $self = shift;
my $cars_ref = $self->get_cars;
my $count = @{keys %$cars_ref};
return $count;
}
# add other "collective" methods
1;
PS: nice you're not using an OOP framework, because you don't need one xD
PPS: So I suggested the opposite of what you asked. But you can do the same with a "OutRented" container class. The point is to use a container class the has some knowledge of the class it's containing. | [reply] [Watch: Dir/Any] [d/l] [select] |
Re: oop, variable that counts the number of objects created
by jcb (Parson) on Jul 31, 2020 at 01:46 UTC
|
A technique I used to allow testing code to verify correct object destruction of some classes that use weak references to break cycles was something like:
package Whatever;
sub new {
my $class = shift;
my $ob = {};
# ...
{ our $_total_constructed; $_total_constructed++ }
bless $ob, $class
}
sub DESTROY { our $_total_destroyed; $_total_destroyed++ }
The test scripts can then access those package variables and verify that $Whatever::_total_constructed and $Whatever::_total_destroyed are equal at the end of a test run after the last lexical holding an object has gone out of scope. | [reply] [Watch: Dir/Any] [d/l] [select] |
Re: oop, variable that counts the number of objects created
by Anonymous Monk on Jul 30, 2020 at 10:33 UTC
|
Thank you all for replying, you've made me a little bit wiser.
| [reply] [Watch: Dir/Any] |
Re: oop, variable that counts the number of objects created
by karlgoethebier (Abbot) on Jul 30, 2020 at 10:39 UTC
|
Possibly overkill but MCE::Shared::Scalar might be an option. And yes, I would use a framework. You may take a look at Class::Tiny and Role::Tiny. Regards, Karl P.S.: Consider a Porsche instead of a Firebird.
«The Crux of the Biscuit is the Apostrophe»
perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help
| [reply] [Watch: Dir/Any] [d/l] |