in reply to OO - inside-out or by means of a anonymous sub?

As I see things, the biggest advantage of using inside-out object is typo checking. $self->{attribute} becomes $attribute{$self}, which allows typos of attribute to be caught at compile time, rather than having them lead to weird problems at run-time. You mitigated this by providing accessors, but not by using closures.

Inside-out objects also provide data protection. If the attribute hash is a my variable, neither the main program nor other modules can access the attributes without using the accessors. Howver, in your closure code, anyone can do &{ $obj }("BALANCE", '1000000');. True, sanity checks could be added inside the closure, but inside-out objects could ban access to BALANCE completely.

Replies are listed 'Best First'.
Re^2: OO - inside-out or by means of a anonymous sub?
by xdg (Monsignor) on Jan 12, 2006 at 21:40 UTC
    $self->{attribute} becomes $attribute{$self}

    Minor nit: it should be $attribute{ refaddr $self }. Just plain $self will break if stringification is overloaded.

    Inside-out objects also provide data protection.

    As I see it, encapsulation is not synonymous with data protection. Encapsulation means providing a set interface for interaction such that other parts of the program do not need to take into account the internal implementation of the object. Regular Perl objects can only provide incomplete encapsulation, even with interface methods, because subclasses must use the same underlying data structure. If the parent class changes its implementation, the subclass will break. That's an encapsulation failure.

    Inside-out objects can provide complete encapsulation, but this is only true if the memory address is used directly as the index into the property data structures. Inside-out objects that cache an identifier or memory address inside a blessed scalar (as Class::Std does, for example) are also mandating a data structure and thus fail to completely encapsulate the implementation.

    -xdg

    Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Re^2: OO - inside-out or by means of a anonymous sub?
by Roy Johnson (Monsignor) on Jan 12, 2006 at 16:26 UTC
    My take on typo checking is that attributes should be accessed by variables (or constants) rather than by strings. Coincidentally, that makes indexing an arrayref just as convenient as indexing a hashref.

    $self->{attribute} becomes $self->[ATTRIBUTE] (where ATTRIBUTE is an integer constant). Those constants should not be visible outside of the package published or exported, because they're an implementation detail.

    Admittedly, the initialization code becomes a bit less beautiful, but it's still perfectly clear:

    sub new { my ($class) = @_; my @obj; @obj[ACCOUNT, NAME, BALANCE] = (undef, undef, 0); return bless( \@obj, $class); }
    Variations on this that avoid declaring an array would probably be uglier.

    Caution: Contents may have been coded under pressure.
      I use the method you describe as well. However, I'm curious how you hide the constants from other packages. ("Those constants should not be visible outside of the package") It could be done if they were lexical variables, but there's no $ on your constants.