+ -
当前位置:首页 → 问答吧 → 请教use module和@ISA的区别

请教use module和@ISA的区别

时间:2011-02-17

来源:互联网

本帖最后由 seufy88 于 2011-02-17 11:27 编辑

刚刚看完对象这一章,我有点迷糊
我自己写了个试验一下
----------------------------------------
A.pm代码如下:
package A;
use Exporter;
@Export=qw(foo);
sub foo{
print "this is a method in A.pm
};
-----------------------------------------
B.pm代码如下:
package B;
use Exporter;
use A;
@Export=qw(barney);
sub barney{
print "this is a method in B.pm
};

-----------------------------------------

test.pl
use B;
foo;
barney;
-----------------------------------------
能够正常输出:
this is a method in A.pm
this is a method in B.pm

1.这个和继承有什么区别吗?外面模块的符号引入和继承这两个知识点各有什么不同
2.use module的形式,是不是很容易造成“符号”的重名?
use A,而A.pm中又use B,而B.pm中又use C,最后用户的脚本use A,这样就把A,B,C所有默认的符号都引入了
3.书上一直说如果在当前包中找不到方法,就到@ISA中列举的包中去寻找,请问
---------------------------------------
package D;
use Exporter;
@Export=qw(foo);
sub foo{
print "this is a method in D.pm
};

----------------------------------------

package C;
@ISA=qw(A);
use D;
sub new{...} #Construtor;
.......
---------------------------------------
#!/usr/bin/perl
$obj=C->new;
$obj->foo;
---------------------------------------
D.pm和A.pm中都定义了方法foo,那继承和use module这两个在这里会用哪个?

作者: seufy88   发布时间: 2011-02-17

我的理解是use在编译时把包变量倒入到当前包,而继承则是靠@ISA来实现的,继承搜索的规则是从左到右,深度优先
  1. #!/usr/bin/perl

  2. package A;

  3. sub new {
  4.         my $class = shift;
  5.         $class = ref($class) || $class;
  6.         my $self = {};
  7.         return bless $self , $class;
  8. };

  9. sub myprint {
  10.         print "i am in A\n";
  11. };

  12. package B;
  13. @ISA=qw/A C/;

  14. sub myprint {
  15.        print "i am in B\n";
  16. };

  17. package C;

  18. sub new {
  19.         my $class = shift;
  20.         $class = ref($class) || $class;
  21.         my $self = {};
  22.         return bless $self , $class;
  23. };

  24. sub myprint {
  25.         print "i am in C\n";
  26. };

  27. package main;
  28. use B;
  29. my $obj = new B;
  30. $obj->myprint();
复制代码
输出为:
i am in B
删除B中的方法,那么输出为:
i am in A
对换·@ISA列表中的 A C为C A
输出为
i am in C

作者: justlooks   发布时间: 2011-02-17

导入函数是在这个包里搞个别名,继承是OO基本不沾边啊

导入函数后来的会覆盖之前的,继承也只有在方法调用的时候出现很容易区分

作者: zhlong8   发布时间: 2011-02-17

回复 justlooks


先谢谢

作者: seufy88   发布时间: 2011-02-17

本帖最后由 seufy88 于 2011-02-17 10:33 编辑


QUOTE:
导入函数是在这个包里搞个别名,继承是OO基本不沾边啊

导入函数后来的会覆盖之前的,继承也只有在方法调 ...
zhlong8 发表于 2011-02-17 10:22




    谢谢 ,其实我想明白导入函数和继承方法同名时,会是个什么样情况

"导入函数是在这个包里搞个别名"那这个包如果返回一个对象$obj,那可不可以像调用实例方法一样去调用导入函数?
"$obj->导入函数"这样的形式?
按你的意思,是不是继承的方法能用$obj->的形式,而导入函数不能用$obj->去调用?

我第二个例子就是这样的情况

作者: seufy88   发布时间: 2011-02-17



QUOTE:
谢谢 ,其实我想明白导入函数和继承方法同名时,会是个什么样情况
按你的意思,继承的方法只 ...
seufy88 发表于 2011-02-17 10:27




    导入函数能用$obj->去调用,导入的函数和你自己在包里定义的函数是同等地位的。如果你导入了那就等于这个类就有这个方法了,当然就不会继承了

作者: zhlong8   发布时间: 2011-02-17



QUOTE:
导入函数能用$obj->去调用,导入的函数和你自己在包里定义的函数是同等地位的。如果你导入了那就 ...
zhlong8 发表于 2011-02-17 10:32




    非常非常感谢你的回答.这么一说我就明白啦.祝大家元宵快乐

作者: seufy88   发布时间: 2011-02-17

回复 seufy88


    那肯定是A里面的东西啊,在编译时已经导入这个包的函数了,所以你调用的时候不会发生继承

作者: justlooks   发布时间: 2011-02-17



QUOTE:
回复  seufy88


    那肯定是A里面的东西啊,在编译时已经导入这个包的函数了,所以你调用的时候不会发 ...
justlooks 发表于 2011-02-17 10:34




    恩恩,偶明白啦.
还有一个问题,既然导入函数和继承都是从"外部模块"实现的,当前包都没有这个定义,那什么情况下用导入函数,什么情况下用继承好呢?总感觉大家这么一解释,他们俩可以"互换",比如将原先i当前包继承的那个类取消继承,改为use ,好像也能达到同样的效果哈?反之也一样

作者: seufy88   发布时间: 2011-02-17



QUOTE:
恩恩,偶明白啦.
还有一个问题,既然导入函数和继承都是从"外部模块"实现的,当前包都没有这个定义 ...
seufy88 发表于 2011-02-17 10:39




    导入会污染当然包的符号表,如果你是按 OO 风格设计的相关方法当然用继承,最终都是函数的调用

作者: zhlong8   发布时间: 2011-02-17

本帖最后由 seufy88 于 2011-02-17 10:50 编辑


QUOTE:
导入会污染当然包的符号表,如果你是按 OO 风格设计的相关方法当然用继承,最终都是函数的调用
zhlong8 发表于 2011-02-17 10:44




    "污染"这词太达意了
PS:原来符号的导入可以"迭代"的

作者: seufy88   发布时间: 2011-02-17

本帖最后由 seufy88 于 2011-02-17 11:15 编辑


QUOTE:
回复  seufy88


    那肯定是A里面的东西啊,在编译时已经导入这个包的函数了,所以你调用的时候不会发 ...
justlooks 发表于 2011-02-17 10:34




试了一个,果然是A,但按理是D才是阿?不是已经use D了么,那应该不会继承才是的呀

------------------------------------------
D.pm

package D;
use Exporter;
@Export=qw(foo);
sub foo{
print "this is a method in D.pm
};
------------------------------------------



package A;
use Exporter;
@Export=qw(foo);
sub foo{
print "this is a method in A.pm
};

package C;
@ISA=qw(A);
use D;
sub new{...} #Construtor;

package main
#!/usr/bin/perl
$obj=C->new;
$obj->foo;

作者: seufy88   发布时间: 2011-02-17



QUOTE:
我的理解是use在编译时把包变量倒入到当前包



其实就是用typeglob做的一个别名,并不是变量copy。

作者: 兰花仙子   发布时间: 2011-02-17



QUOTE:
其实就是用typeglob做的一个别名,并不是变量copy。
兰花仙子 发表于 2011-02-17 11:20




   偶一开始看typeglob不适应,为什么要是*来glob,再用funny character来区别类型,其他语言中好像没这么glob的呀.
后来看到可以直接对特定类型变量进行alias才适应.
请问仙子typeglob现在用的多吗?好像在书中很少看到别名了,除了在符号表里,大多是引用来着

作者: seufy88   发布时间: 2011-02-17



QUOTE:
偶一开始看typeglob不适应,为什么要是*来glob,再用funny character来区别类型,其他语言中好像没这 ...
seufy88 发表于 2011-02-17 11:24




    用的很少。一些高级类库在背后是使用了typeglob的,你只需要用那些库就可以了。

作者: 兰花仙子   发布时间: 2011-02-17

建议学习 Moose ,非常优秀的 oo 体系。
学了这个,写 perl oo 程序非常简单。

作者: horsley   发布时间: 2011-02-17

不懂 typeglob 就不可能完全懂 模块、OO、特殊变量、作用域、IO 和众多 hack 技巧

作者: zhlong8   发布时间: 2011-02-17