Eobj
view release on metacpan or search on metacpan
#
# A copy of the license can be found in a file named "licence.txt", at the
# root directory of this project.
#
use Eobj::PLerror;
package Eobj;
use Eobj::PLerror;
use 5.004;
use strict 'vars';
use warnings;
require Exporter;
BEGIN {
@Eobj::warnings = ();
%Eobj::classes = ();
$SIG{__WARN__} = sub {
my ($class) = ($_[0] =~ /unquoted string.*?\"(.*?)\".*may clash/i);
if (defined $class) {
push @Eobj::warnings, $_[0];
} else {
warn ($_[0])
}
};
}
END {
$SIG{__WARN__} = sub {warn $_[0]; }; # Prevent an endless recursion
foreach (@Eobj::warnings) {
my ($class) = ($_ =~ /unquoted string.*?\"(.*?)\".*may clash/i);
warn ($_)
unless (defined $Eobj::classes{$class});
}
# Now we destroy all objects in an orderly fashion...
foreach (sort { $b->get('eobj-object-count') <=> $a->get('eobj-object-count') }
values %Eobj::objects) {
$_->survivor();
$_->destroy();
}
}
# We use explicit package names rather than Perl 5.6.0's "our", so
# perl 5.004 won't yell at us.
@Eobj::ISA = qw[Exporter];
@Eobj::EXPORT = qw[&init &override &underride &inherit &inheritdir &definedclass &globalobj];
$Eobj::VERSION = '0.23';
$Eobj::STARTTIME = localtime();
$Eobj::eobjflag = 0;
$Eobj::globalobject=();
unless ($Eobj::eobjflag) {
$Eobj::eobjflag = 1; # Indicate that this clause has been run once
$Eobj::errorcrawl='system';
$Eobj::callbacksdepth = 0; # This indicates when callbacks are going on.
undef $Eobj::wrong_flag;
#For unloaded classes: Value is [classfile, parent class, first-given classname].
%Eobj::classes = ('PL_hardroot', 1);
%Eobj::objects = ();
$Eobj::objectcounter = 0;
{
my $home = $INC{'Eobj.pm'};
($home) = ($home =~ /^(.*)Eobj\.pm$/);
blow("Failed to resolve Eobj.pm's directory")
unless (defined $home);
$Eobj::home = $home;
}
$Eobj::classhome = "${Eobj::home}Eobj/";
inherit('root',"${Eobj::classhome}PLroot.pl",'PL_hardroot');
inherit('global',"${Eobj::classhome}PLglobal.pl",'root');
inherit('site_init',"${Eobj::classhome}site_init.pl",'PL_hardroot');
}
sub init {
site_init -> init;
}
sub inherit {
my $class = shift;
my $file = shift;
my $papa = shift;
puke("Attempt to create the already existing class \'$class\'\n")
if $Eobj::classes{$class};
puke("No parent class defined for \'$class\'\n")
unless (defined $papa);
$Eobj::classes{$class} = [$file, $papa, $class];
# The following two lines are a Perl 5.8.0 bug workaround (early
# versions). Google "stash autoload" for why.
undef ${"${class}::Eobj_dummy_variable"};
undef ${"${class}::Eobj_dummy_variable"}; # No single use warning...
return 1;
}
sub inheritdir {
my $dir = shift;
my $papa = shift;
($dir) = ($dir =~ /^(.*?)[\/\\]*$/); # Remove trailing slashes
blow("Nonexistent directory \'$dir\'\n")
unless (-d $dir);
do_inheritdir($dir, $papa);
return 1;
}
sub do_inheritdir {
my $dir = shift;
my $papa = shift;
($dir) = ($dir =~ /^(.*?)[\/\\]*$/); # Remove trailing slashes
global object is done with something like
my $global = $self->globalobj;
=back
=head1 HOW TO DIE
Eobj comes with an error-reporting mechanism, which is based upon the Carp module.
It's was extended in order to give messages that fit Eobj better.
There are two main functions to use instead of die(): blow() and puke(). They are
both used like die() in the sense that a newline in the end of the error message
inhibits prinitng the file name and line number of where the error happened.
=over 4
=item *
blow() should be used when the error doesn't imply a bug. A failure to open a file,
wrong command line parameters are examples of when blow() is better used. Note that
if you use blow() inside a class, it's usually better to give a descriptive error
message, and terminate it with a newline. Otherwise, the class source file will be
given as where the error occured, which will make it look as if there's a bug in
the class itself.
=item *
puke() is useful to report errors that should never happen. In other words, they
report bugs, either in your class or whoever used it. puke() displays the entire call
trace, so that the problematic call can be found easier.
=back
For warnings, fishy() is like blow() and wiz() works like puke(). Only these are warnings.
Unlike Carp, there is no attepmt to distinguish between the "original caller", or the
"real script" and "modules" or "classes". Since classes are readily written per
application, there is no way to draw the line between "module" and "application".
It is possible to declare a class as "hidden" or "system", which will make it disappear
from stack traces. This is explained in the programmer's guide.
=head1 ISSUES NOT COVERED
The following issues are covered in the Eobj programmer's guide (F<eobj.pdf>), and not in this
man page. Just so you know what you're missing out... ;)
=over 4
=item *
The override() and underride() functions
=item *
Constant properties
=item *
Magic callbacks: How to make properties depend on each other.
=item *
Setting up properties during object creation with new()
=item *
List operations on properties: pshift(), punshift(), ppush() and ppop()
=item *
The property path: A way organize properties in a directory-like tree.
=item *
Several useful methods of the C<root> class: who(), safewho(), isobject(),
objbyname(), prettyval() and linebreak()
=back
=head1 EXPORT
The following functions are exported to the main script:
init(), override(), underride(), inherit(), inheritdir(), definedclass(), globalobj()
These functions are exported everywhere (can be used by classes as well):
blow(), puke(), wiz(), wizreport(), fishy(), wrong(), say(), hint(), wink()
These methods are part of the C<root> class, and should not be overridden
unless an intentional change in their functionality is desired:
new(), destroy(), survivor(), who(), safewho(), isobject(), objbyname(),
suggestname(), get(), const(), set(), seteq(), addmagic(), pshift(), ppop(),
punshift(), ppush(), globalobj(), linebreak(), objdump(), prettyval()
store_hash(), domutate(), getraw()
Note that the last three methods are for the class' internal use only.
=head1 HISTORY
Eobj is derived from a larger project, Perlilog, which was written in 2002 by the same
author.
A special OO environment was written in order to handle objects conveniently. This
environment was later on extracted from Perlilog, and became Eobj.
=head1 BUGS
Please send bug reports directly to the author, to the e-mail given below. Since Eobj
relies on some uncommonly used (but yet standard) features, the bug is sometimes in
Perl and not Eobj. In order to verify this, please send your version description
as given by running Perl with C<perl -V> (a capital V!).
These are the bugs that are known as of yet:
=over 4
=item *
( run in 2.346 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )