Can't locate object method via package subclassing DBI
this is my first foray into subclassi开发者_JAVA技巧ng 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
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
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';
...
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.
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}'
...
;
精彩评论