11

As I know, creating dynamic instances of a class (package) is like a hack on Perl syntax (using 'bless'). Perl doesn't support a keyword called 'class'; thus everything is limited.

The first limitation of Perl which causes difficulty in OOP is when creating static class properties and static class methods. Any solution?

nicola
  • 2,141
  • 1
  • 19
  • 19

4 Answers4

18

For class-level variables there are two commonly used approaches:

package Bar;
use strict;
use warnings;

sub new { bless {}, shift };

# (1) Use a lexical variable scoped at the file level,
# and provide access via a method.
my $foo = 123;
sub get_foo { $foo }

# (2) Use a package variable. Users will be able to get access via
# the fully qualified name ($Bar::fubb) or by importing the name (if
# your class exports it).
our $fubb = 456;

Example usage:

use Bar;

my $b = Bar->new;
print "$_\n" for $b->get_foo(), $Bar::fubb;
FMc
  • 41,963
  • 13
  • 79
  • 132
  • i don't know why $Bar::fubb always gives me blank, and thus i have to use 'get','set' methods to read & write the variable in package – nicola Apr 04 '11 at 13:56
  • @nicola with `our` it is possible to access the variable externally, with `my` it is not. If it's still not working with `our` I'd be interested to see the code. – Andy Apr 04 '11 at 15:10
6

In this day and age, if you really want to do OOP with Perl, you'd be well advised to use an object framework like Moose that will help clean up the crufty syntax. It will make doing OO in Perl hurt a lot less, and if you use extensions like MooseX::Declare, it'll be even sweeter.

I don't do a whole lot of OO stuff, but I think I know what you're trying to do, and I do believe Moose can make it straight forward to do so.

BadFileMagic
  • 701
  • 3
  • 7
  • Static things with Moose have been [explained here with a comprehensive code example](http://stackoverflow.com/questions/7587157/how-can-i-set-a-static-variable-that-can-be-accessed-by-all-subclasses-of-the-sa). – smonff Jan 04 '14 at 14:11
1

I've found a solution:

package test;

my $static_var = undef;

#constructor not needed

#static method to set variable
sub set_var {
    my ($value) = @_;
    $static_var = $value;
}

#static method to get variable value
sub get_var {
    return $static_var;
}

1;

According to http://www.stonehenge.com/merlyn/UnixReview/col46.html, it doesn't seem possible to access those variables in package directly. Maybe there must be get, set methods to access them.

As said in the above article:

There's also no syntax that would let any other code outside of this code access those variables, so we can be assured that our variables won't be changing mysteriously.

I don't really know whether that author is right.

daxim
  • 39,270
  • 4
  • 65
  • 132
nicola
  • 2,141
  • 1
  • 19
  • 19
  • however i still don't know how to access the $static_var directly yet, presently i can access it only through subroutines like set_var, get_var above – nicola Apr 04 '11 at 10:44
  • 3
    "i don't really know whether that author is right". You can generally trust merlyn on these things :-) – Dave Cross Apr 04 '11 at 15:17
  • 1
    what davorg was trying to say via a healthy dose of irony is that merlyn is actually Randal Schwartz (http://en.wikipedia.org/wiki/Randal_L._Schwartz), (co)-author of several main Perl books (Camel/Llama/Alpaka O'Reilly Perl books among them) and one of the oldest, most well known and respected Perl hackers. – DVK Apr 04 '11 at 23:24
  • but it seems accessible if we declare the variable with 'our' keyword? – nicola Apr 05 '11 at 03:18
  • 'our' is sort of a fudge, it allows you code to pass the 'use strict' test, but basically means there is no access control on the variable. – thecoshman Dec 12 '12 at 13:56
0

A standard package variable behaves as a class variable

package foo;

my $bar;

1;

then:

$foo::bar=1;  # or whatever
$foo::bar++;
print $foo::bar, "\n";
epitaph
  • 9
  • 1
  • the "print $foo::bar" gives me a blank string, u know y? – nicola Apr 04 '11 at 13:52
  • 2
    That's never going to work. my $bar creates a lexical variable, but $foo::bar is trying to access a package variable. – Dave Cross Apr 04 '11 at 15:16
  • 2
    You need to `s/my/our/`, `our` creates a short lexical alias for a package variable, whereas `my` creates a lexical variable that does not live in a package (and is thus not accessible via a fully qualified package name) – Eric Strom Apr 04 '11 at 17:55