免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 5547 | 回复: 24
打印 上一主题 下一主题

关于perl 里类的实现的一些疑惑 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-12-07 17:26 |只看该作者 |倒序浏览
我一直对perl 里类的实现和使用有些迷糊, 书也看了, 但还是有些晕晕呼呼, 我觉得还是讨论来的快, 所以在此写一下关于我自己对perl类的理解, 希望大家能给于指点:
我的理解:
首先perl 的类就是一个包, 在这个包里定义的函数就是类的方法.
类整个的实现,是通过一个匿名hash引用实现的
通过hash 这种数据结构, 一个变量就可以映射一个复杂的数据结构, 这个变量也就是这个hash的引用.

my $self = {};
$self->{data1} = 1;
$self->{data2} = 2;
以上是数据的上, hash 对类的实现,
*问题1.  那么类的方法(包里函数)怎么实现的?
是hash 里面存了 子函数的引用? 然后就可以通过这个引用来调用函数,达到了类里对方法的调用的目的?

*问题2. 为什么类的方法的第一个参数都是类本身(那个引用变量)
因为这个类整个就是一个hash ,所以如果要操作类的数据(hash的数据), 就要通过hash的引用来访问,所以在类的方法体里, 需要一个这样的变量, 来对hash本身的数据,方法进行操作. 这样理解对不? :)


sub new {
    my $class = shift;
    my $self = {};
    bless $self,$class;
    return $self;
    }

*问题3. 每个类都会有个初始化函数new, 这new 是创造这个hash的地方. 但为啥也要先shift 一个class, 这个时候,那个承载类的hash应该还没有创建吧, 这个shift ,会得到什么? 还是根本就没用, 只是声明了个变量?

问题4. 哪位明白的高人,给解释一下bless, 是干啥的,  如果以上代码这样写
sub new {
    my $class = shift;
    my $self = {};
    $class = $class;
    return $self;
    }
效果是不是一样呢?

大概就这些困惑吧, 主要是对perl里类的实现机制没个清晰的把握, 希望已经明白的, 有经验的兄弟或姐妹能深入的谈一下, 自己的理解 , 谢谢了

希望讨论使大家对perl 的类有一个更清晰的理解, 能够对困惑, 迷糊朋友有所帮助!!

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
2 [报告]
发表于 2006-12-07 17:57 |只看该作者
问题1的回答:
hash 里面没有存它的方法,这完全是 -> 操作符的功劳。-> 操作符其实也没有什么神秘之处,它只不过是调用了一下它右边的那个 sub(注),并且把左边的那个引用变量 unshift 到 sub 的参数列表中去。注:为了正确地找到右边的那个 sub,它还需要把左边的那个引用变量 ref 一下取出原先 bless 进去的那个 tag

问题2的回答:
你理解的是正确的。

问题3的回答:
new 的第一个参数是 $class,不是 $self,也就是说,new 的第一个参数是类名称,而不是对象,你估计是自己把自己绕糊涂了,根本就不存在你所说的“那个承载类的hash应该还没有创建吧”的问题——你该不会连“类”和“类的实例”这两个概念都搞不清楚吧?

问题4的回答:
bless 的作用是给第一个参数(必须是个引用)打上一个印记(就好像盖个戳一样),而这个印记就标明了这个引用从此以后应该属于哪个类。理解了这个之后,你就明白 bless $self, $class 和 $class = $self 其实是完全不同的东西。bless $self, $class 之后,$class 还是原来的值,$self 也还是原来的值,只不过 $self 的印记变成了 $class 的内容。$class = $self 则是把 $class 变成和 $self 值相同的一个变量。

题外话:
1,new 的名称不是 Perl 语法的一部分,你完全可以叫 create, construct, build, 或者别的东西。
2,对象也不一定要用 hash 引用来存储数据,事实上任何类型的引用都可以,只不过 hash 引用正好方便表示 OOP 里面的“属性=>值”这种模型而已。事实上,CPAN 上就有一组用数组引用来构造类体系的,更加省空间。
3,Perl 对 OOP 提供的语法很有限,但是支持 OOP 的大多数概念。这些有限的语法包括 bless 函数、package 语句、-> 操作符、还有 @ISA 数组,以及 SUPER UNIVERSAL 等有限的几个关键字。除此以外我想再没有别的东西了。

论坛徽章:
0
3 [报告]
发表于 2006-12-07 23:10 |只看该作者
不错的discuss哦,UP下.

论坛徽章:
0
4 [报告]
发表于 2006-12-07 23:39 |只看该作者
俺已经加收藏了,就等来人继续讨论了

论坛徽章:
0
5 [报告]
发表于 2006-12-08 07:31 |只看该作者
you can check perlboot carefully, you should get the point of why shift should be used!

Another document should give you the clear answer for the questions,
Perl Objects, References & Modules

In the perl module:
on class method, first you should get the calling object instance from implied first arguments,
this could be got by using the shift functions, then you could make calculation based on the object currently you calling.

BTW, Perl's the data_encapsulation is not so strict, so sometime for easy operation, you may directly modified the object's data from outside world, but from my point of view, this should be avoided.

in the end, the existing perl module can give you the most practical example/clue.

论坛徽章:
0
6 [报告]
发表于 2006-12-08 10:17 |只看该作者
好文,加深了对perl面向对象的理解.

论坛徽章:
0
7 [报告]
发表于 2006-12-08 17:06 |只看该作者

谢谢 flw 兄的指点

关于指点1 我理解:
$object = new Class;
$object -> sub_a();

$object 就是这个类的对象 , sub_a() 时类的方法
"->" 把$object  unshift  到 sub_a() 的参数列表里,
所以在sub_a () 函数体里
sub_a(){
  my $self = shift ;
}
这个$self 这么样, 就是类的本身了
"->" 的功能原理真是神奇!

关于第3个问题:
"问题3的回答:
new 的第一个参数是 $class,不是 $self,也就是说,new 的第一个参数是类名称,而不是对象,...."
构造函数new 的第一个参数就是类的名字, 一个字符串.
用这个名字,通过bless 给那个hash 引用打上一个标签.

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
8 [报告]
发表于 2006-12-08 17:46 |只看该作者
> 这个$self 这么样, 就是类的本身了 "->" 的功能原理真是神奇!
你这里有点小错误,$self 在你举的这个例子中,是 $object,也就是对象/类实例而不是类。

论坛徽章:
0
9 [报告]
发表于 2007-03-08 14:52 |只看该作者
通过你们的讨论我自己结合做了点总结,但有些地方用语言根本无法形容,哪位高手最好给例子?

类和方法理解
类其实就是一包,而包只不过是perl符号表中名字的集合,方法只不过是perl的一个子程序,
类名是第一参数,因为这个类整个就是一个hash,所以如果要操作类的数据,就要通过hash的引用
来访问,所以在类的方法体里,需要一个这样的变量,来对hash本身的数据,方法进行操作。
因此
   sub new{
    $class=shift  因为类名是第一参数 所以class就是类名?
     $this={}   通过这个引用来访问类的数据
bless $this  $this属于 $class类?

如何对hash类实现:
如$object=new Class;
$object->sub_a();
$object 此是是对象/实例,工作过程,hash本身没有存方法,这完全是->符号的功劳,它只不过是调

用了一下它右边的那个sub 并把左边的那个引用变量unshift到sub的参数列表中去,为了正确的找到
右边的那个sub,它还需要把左边的那个引用变量ref一下取出原先bless进去的那个。
因此在子程序 sub_a(){
   my $self=shift; 的时候$self就得到了引用变量$object 因此它成为对象/实例

类方法和实例方法

实例方法其主要

实例也就是之前的$this={}引用,而对象通过执行某种动作取其行为,因此实例方法也叫对象方法,而类方法则是针对于整个类??

[ 本帖最后由 knuoxy 于 2007-3-8 14:59 编辑 ]

论坛徽章:
0
10 [报告]
发表于 2007-03-08 15:11 |只看该作者
一个hash引用被bless到某一个包中,Perl就完成了一个类的设计。
如果你写下$objref->submethod(@parms),(我猜想,至少你可以这样理解)Perl编译器就会把这个调用转化为如下的调用
$package::submethod($objref, @parms), 其中$package就是$objref被应用的包,
这样你就明白了吧,你在编写$package::submethod方法时,你可以使用$_[0]作为你要操作的对象了。
$package->submethod(@parms)调用被替换成
$package::submethod($package, @parms),
这样你在这个方法中就可以使用$_[0]得到$package了。

其他的都不过是对一个hash引用或者数组引用的操作而已。

很好理解啊。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP