问题
this is my first foray into subclassing with perl and I am wondering why I am getting this simple error...
"Can't locate object method "prepare" via package "WebDB::st" at /home/dblibs/WebDB.pm line 19.". It seems to find the module WebDB ok, but not the prepare subroutine in ::st
First here's my package (both packages are in one file, WebDB.pm)
package WebDB;
use strict;
use DBI;
sub connect {
my $dbh = (DBI->connect ("DBI:mysql:test:127.0.0.1", "root","",
{ PrintError => 1, RaiseError => 0 }));
return bless $dbh, 'WebDB::st';
}
package WebDB::st;
our @ISA = qw(::st);
sub prepare {
my ($self, $str, @args) = @_;
$self->SUPER::prepare("/* userid:$ENV{USER} */ $str", @args);
}
1;
I also tried replacing the "our @ISA = qw(;;st)" with "use base 'WebDB'" and same problem. I'm thinking it's probably something very simple that I'm overlooking. Many thanks! Jane
回答1:
Subclassing DBI has to be done just right to work correctly. Read Subclassing the DBI carefully and properly set RootClass (or explicitly call connect on your root class with @ISA set to DBI). Make sure you have WebDB::st subclassing DBI::st and a WebDB::db class subclassing DBI::db (even if there are no methods being overridden). No need to rebless.
Avoid using base
; it has some unfortunate behavior that has led to its deprecation, particularly when used with classes that are not in a file of their own.
Either explicitly set @ISA or use the newer parent
pragma:
package WebDB;
use parent 'DBI';
...
package WebDB::db;
use parent -norequire => 'DBI::db';
...
package WebDB::st;
use parent -norequire => 'DBI::st';
...
回答2:
Are WebDB
and WebDB::st
in one file or two? If they are in separate files, I don't see anything that is doing a use WebDB::st;
, which would cause that file to be loaded.
You can do either of these things as a remedy -- put the two packages in the same file (that would look exactly as you have pasted it above), or add a use WebDB::st;
line in WebDB.pm.
(I'd also add use strict; use warnings;
in both these packages too.)
Also, the prepare function is not in ::st
-- there is no such package (unless it is defined elsewhere). prepare
is in the WebDB::st
namespace -- via the package
declaration. You are however declaring that WebDB::st
has ::st
as a parent.
回答3:
If subclassing is as tricky as ysth seems to think, I might recommend Class::Delegator from CPAN. I use if for classes that want to act like IO
. And by it, Perl is the first language (that I am aware of) that has an expression language for aggregation, delegation, encapsulation almost equal with inheritance.
package WebDB;
use strict;
use DBI;
use Class::Delegator
send => [ qw<connect ...> ]
, to => '{_dbihandle}'
...
;
来源:https://stackoverflow.com/questions/4136099/cant-locate-object-method-via-package-subclassing-dbi