Hãy xem chương trình package MyCommonPkg.pm
và xem nội dung nó nói. Liệu nó có cái gì như thế này?
package MyCommonPkg;
use Exporter qw(import); # Might be "require" and not "use"
our @EXPORT = qw(thisSubroutineIsNotDefinedAnywhereElse);
Cú pháp có thể khác đôi chút. Những điều chính bạn sẽ thấy là tuyên bố package
, rằng nó sử dụng Exporter
và mảng @EXPORT
có tên chương trình con của bạn trong đó.
Điều đang xảy ra là xung đột không gian tên. Gói của bạn đang xác định cùng một chương trình con mà bạn đang xác định.
Để ngăn chặn điều này xảy ra, Perl sử dụng các không gian tên. Theo mặc định, không gian tên của bạn là main
. Tuy nhiên, các gói được giả định để xác định các tên riêng của chúng bằng cách sử dụng lệnh package
.
Không gian tên đầy đủ của một chương trình con hoặc biến là không gian tên được theo sau bởi dấu hai chấm, theo sau là tên chương trình con hoặc tên biến. Ví dụ: bạn xem File::Find, bạn sẽ thấy tham chiếu đến các biến $File::Find::name
và $File::Find::dir
. Đây là các biến số $name
và $dir
bên trong gói File/Find.pm
trong không gian tên File::Find
.
Để giúp mọi thứ dễ dàng hơn cho bạn, gói có thể xuất biến và chương trình con của chúng vào không gian tên chính của bạn. Ví dụ, nếu tôi sử dụng File::Copy, O có thể làm điều này:
...
use File::Copy
...
copy ($file, $to_dir);
Thay vì:
...
use File::Copy
...
File::Copy::copy ($file, $to_dir);
Nếu bạn nhìn vào File/Copy.pm
, bạn sẽ thấy như sau:
package File::Copy;
...
our(@ISA, @EXPORT, @EXPORT_OK, $VERSION, $Too_Big, $Syscopy_is_copy);
...
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(copy move);
Các package File::Copy;
xác định không gian tên. require Exporter;
và @ISA = qw(Exporter)
cho phép gói xuất các chương trình con và các biến vào không gian tên chính chính. @EXPORT
tự động, không có thông báo cho bạn bất kỳ điều gì, hãy nhập các tiểu trình copy
và move
vào các không gian tên chínhcho dù bạn có muốn hay không!
Điều cuối cùng là rất quan trọng. Hiện được coi là cách cư xử xấu để sử dụng @EXPORT
. Thay vào đó, bạn nên sử dụng @EXPORT_OK
yêu cầu bạn liệt kê các chương trình con mà bạn muốn sử dụng. Các gói hiện đại hơn như Scalar::Util làm điều này.
Rất nhiều thứ. Trước tiên, số MyCommonPkg
của bạn có tuyên bố package MyCommonPkg;
. Nếu không, nó nên. Điều này giúp các gói con và các biến không ảnh hưởng đến chương trình của bạn theo những cách khó chịu. Sau đó, bạn có thể sử dụng @EXPORT
hoặc @EXPORT_OK
.
Nếu MyCommonPkg
có tuyên bố package
, có sử dụng @EXPORT
không? Nếu có, bạn có một số cách để tránh vấn đề này:
- Bỏ qua cảnh báo. Nó chỉ là một cảnh báo. Vì bạn biết bạn đang xác định lại chương trình con, và bạn muốn sử dụng định nghĩa của chương trình con, hãy bỏ qua nó.
Bạn có thể làm điều này để tắt các cảnh báo khi bạn xác định lại chương trình con:
use MyCommonPkg;
no warnings qw(redefine);
sub thisSubroutineIsNotDefinedAnywhereElse {
...
}
use warnings qw(redefine);
- Sử dụng
require MyCommonPkg;
thay vì use MyCommonPkg;
.Điều này sẽ ngăn việc nhập mọi chương trình con hoặc biến số vào không gian tên của bạn bao gồm cả những thứ bạn muốn sử dụng. Giả sử MyCommonPkg
xác định bốn chương trình con: thisSubroutineIsNotDefinedAnywhereElse
, foo
, bar
và barfoo
. Để sử dụng bất kỳ chương trình con nào.
Bạn cần phải làm điều này:
my $answer = MyCommonPkg::foo($input);
Không vui vẻ.
Sử dụng tên khác cho chương trình con của bạn. Cần phải có tài liệu rằng chương trình con này được định nghĩa trong MyCommonPkg
và nếu bạn muốn sử dụng MyCommonPkg
, bạn không nên sử dụng các tên chương trình con được xuất.
Cuối cùng, nếu MyCommonPkg
là khá mới, và không được sử dụng trong hàng chục chương trình, sử dụng @EXPORT_OK
thay vì @EXPORT
, và chắc chắn rằng tất cả các chương trình sử dụng MyCommonPkg
được sửa đổi để xuất khẩu các chương trình con họ muốn:
như thế này:
use MyCommonPkg qw(foo bar);
Trong trường hợp này, chỉ có thủ tục con foo
và bar
được xuất khẩu. Các chương trình con thisSubroutineIsNotDefinedAnywhereElse
và barfoo
không được xuất vào môi trường của bạn.
Bạn có thực sự khai báo 'gói Common.pm' không? Điều đó có vẻ như là một lỗi. – mob
Bạn có xảy ra hai gói có cùng tên không? Điều đó có thể gây ra một xung đột không gian tên. Luôn đặt tên cho các gói của bạn cho tệp mà chúng đang ở (thay thế '/' bằng '::', và loại bỏ '.pm'). Điều này cũng có thể xảy ra nếu bạn có không gian tên * no *, điều này thực sự có nghĩa là bạn đang ở trong 'main'. – Ether
không - tôi đã không khai báo Common.pm. Tôi chỉ đổi tên mọi thứ để có được một ví dụ mã giả lên và đánh máy. Tôi sẽ chỉnh sửa. – user210757