Hell, if James is showing off large chunks of code in his journal, here's some UNIVERSAL methods I'm toying with adding to our project here. The basic idea was stolen (again) from a Smalltalk idiom.
package UNIVERSAL;
The idea is that you can use this to help implement Model/View/Controller type magic in such a way that the methods of the Model neither know nor care what views there are on it (if any).
use Scalar::Util qw/blessed weaken isweak/;
use overload ();
use strict;
our %__dependents;
sub hash {
my $package = ref $_[0];
return $_[0] unless $package;
require overload;
return "<@" . 0+$_[0]. ">" unless overload::Overloaded($package);
bless $_[0], 'overload::Fake';
my $val = 0 + $_[0];
bless $_[0], $package;
return "<@$val>";
}
sub add_dependent {
my $self = shift;
my $dependent = shift;
unless (blessed($self)) {
require Carp;
Carp::Croak("You can't attach dependents to a class");
}
weaken($__dependents{$self->hash}{$dependent->hash} = $dependent);
}
sub remove_dependent {
my $self = shift;
my $dependent = shift;
unless (blessed ($self)) {
require Carp;
Carp::croak("You can't remove dependents from a class");
}
delete $__dependents{$self->hash}{$dependent->hash};
}
sub dependents {
my $self = shift;
values %{$__dependents{$self->hash}};
}
sub changed {
my $self = shift;
$_->update(@_) for $self->dependents;
}
sub update { }
1;
Updated with a couple of typos fixed. It should compile now...