免费注册 查看新帖 |

Chinaunix

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

Moose学习一例 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-08-01 11:18 |只看该作者 |倒序浏览
如下网上找到关于Moose使用的一个例子,刚接触感觉像天书,网上google一番,看了些资料终于搞明白了。现将整个理解过程简要列一下,希望对大家学Moose有帮助。


  1.     {
  2.         package Point;
  3.         use Moose;

  4.         has 'x' => ( isa => 'Int', is => 'rw' );
  5.         has 'y' => ( isa => 'Int', is => 'rw' );

  6.         use Moose::Util::TypeConstraints;
  7.         subtype 'Point::OrHashRef',
  8.           as 'Point';
  9.         coerce 'Point::OrHashRef',
  10.           from 'HashRef',
  11.           via { Point->new( x => $_->{x}, y => $_->{y} ) };

  12.         sub distance {
  13.             my $start = shift;
  14.             my $end = shift;

  15.             my $dx = $end->x - $start->x;
  16.             my $dy = $end->y - $start->y;
  17.             return sqrt( $dx * $dx + $dy * $dy );
  18.         }
  19.     }

  20.     {
  21.       package Line;
  22.       use Moose;

  23.       # And the same for end
  24.       has ['start', 'end'] => (
  25.           isa => 'Point::OrHashRef',
  26.           coerce => 1,
  27.           is => 'rw',
  28.           required => 1,
  29.           trigger => sub {
  30.               $_[0]->_clear_length();
  31.               return;
  32.           }
  33.       );

  34.       has 'length' => (
  35.           isa => 'Num',
  36.           is => 'ro',
  37.           clearer => '_clear_length',
  38.           lazy => 1,
  39.           default => sub {
  40.               return $_[0]->start->distance( $_[0]->end );
  41.           }
  42.       );
  43.     }


  44.     use Test::More;

  45.     my $line = Line->new(
  46.         start => { x => 1, y => 1 },
  47.         end => Point->new( x => 2, y => 2 )
  48.     );
  49.     isa_ok $line, "Line";
  50.     isa_ok $line->start, "Point";
  51.     isa_ok $line->end, "Point";
  52.     like $line->length, qr/^1.4142135623731/;

  53.     $line->end({ x => 3, y => 3 });
  54.     like $line->length, qr/^2.82842712474619/, "length is rederived";

  55.     done_testing;
复制代码
一、弄懂distance函数是如何实现计算两点间的距离的。
1.1将代码简化为:


  1.     package Point;
  2.     use Moose;

  3.     has 'x' => ( isa => 'Int', is => 'rw' );
  4.     has 'y' => ( isa => 'Int', is => 'rw' );

  5.     sub distance {
  6.         my ( $_, $p ) = @_;
  7.         #对应例子$p1->distance($p2);
  8.         #$_->{x}即$p1 = Point->new( x => 4, ... );
  9.         #$p->{x}即$p2 = Point->new( x => 1, ... );
  10.         my ( $dx, $dy ) = ( $_->{x} - $p->{x}, $_->{y} - $p->{y} );
  11.         return sqrt( $dx * $dx + $dy * $dy );
  12.     }

  13.     package main;
  14.     my $p1 = Point->new( x => 4, y => 5 );
  15.     my $p2 = Point->new( x => 1, y => 1 );

  16.     print 'p1与p2相距距离为:';
  17.     print $p1->distance($p2);
复制代码
1.2将Moose实现的代码转化为传统OO辅助理解(同为网上找到的例子):


  1.     sub Point::new {
  2.       my ($class, $x, $y) = @_;
  3.       bless [$x, $y], $class; # Implicit return
  4.     }
  5.      
  6.     sub Point::distance {
  7.       my ($self, $from) = @_;
  8.       #对应例子$p1->distance($p2);
  9.       #对于传统OO的实现,$self代表$p1,$self[0]即“bless [$x, $y], $class”中的$x这不难理解了吧,同理$from即传入的$p2。
  10.       my ($dx, $dy) = ($self[0] - $from[0], $self[1] - $from[1]);
  11.       sqrt($dx * $dx + $dy * $dy);
  12.     }

  13.     my $p1 = Point->new(4, 5);
  14.     my $p2 = Point->new(1, 1);
  15.     print $p1->distance($p2);
复制代码
至此,Line类中length默认值$_[0]->start->distance( $_[0]->end )即为上例$p1->distance($p2)。

2.1弄明白Moose是如何实现自定义类型,并如何强制实现类型转换的。


  1.     package Point;
  2.     use Moose;
  3.     has 'x' => ( isa => 'Int', is => 'rw' );
  4.     has 'y' => ( isa => 'Int', is => 'rw' );

  5.     #对于new(start => { x => 1, y => 1 },...)函数,我们传给第一个属性的值是个hash引用
  6.     #但测试输出ok 1 - The object isa Point,转变为了Point对象类型。
  7.     use Moose::Util::TypeConstraints;
  8.     #自定义既可以是Point对象类型又可以是HashRef的数据类型,并命名为Point::OrHashRef
  9.     subtype 'Point::OrHashRef', as 'Point';
  10.     #将hash引用($hash={ x => 1, y => 1 })强制转换成Point对象,通过Point->new()来实现,$_->{x}即$hash->{x}
  11.     coerce 'Point::OrHashRef',
  12.       from 'HashRef',
  13.       via { Point->new( x => $_->{x}, y => $_->{y} ) };

  14.     package Line;
  15.     use Moose;

  16.     has [ 'start', 'end' ] => (
  17.         isa => 'Point::OrHashRef',
  18.         coerce => 1,
  19.         is => 'rw'
  20.     );

  21.     package main;
  22.     use Test::More;
  23.     my $line = Line->new(
  24.         start => { x => 1, y => 1 },
  25.         end => Point->new( x => 2, y => 2 )
  26.     );
  27.     isa_ok $line->start, "Point";
  28.     isa_ok $line->end, "Point";
复制代码

评分

参与人数 1可用积分 +6 收起 理由
兰花仙子 + 6 赞一个!

查看全部评分

论坛徽章:
0
2 [报告]
发表于 2014-08-01 16:16 |只看该作者
has 的语法哪里有介绍啊

论坛徽章:
46
15-16赛季CBA联赛之四川
日期:2018-03-27 11:59:132015年亚洲杯之沙特阿拉伯
日期:2015-04-11 17:31:45天蝎座
日期:2015-03-25 16:56:49双鱼座
日期:2015-03-25 16:56:30摩羯座
日期:2015-03-25 16:56:09巳蛇
日期:2015-03-25 16:55:30卯兔
日期:2015-03-25 16:54:29子鼠
日期:2015-03-25 16:53:59申猴
日期:2015-03-25 16:53:29寅虎
日期:2015-03-25 16:52:29羊年新春福章
日期:2015-03-25 16:51:212015亚冠之布里斯班狮吼
日期:2015-07-13 10:44:56
3 [报告]
发表于 2014-08-01 19:33 |只看该作者

论坛徽章:
1
狮子座
日期:2013-12-16 16:09:24
4 [报告]
发表于 2014-08-04 12:21 |只看该作者
回复 3# zhlong8


    现在大概有多少组织/公司在用Moose,
Perl6已经支持OO了,为啥不直接用Perl6?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP