Chinaunix首页 | 论坛 | 博客
  • 博客访问: 226545
  • 博文数量: 36
  • 博客积分: 1188
  • 博客等级: 军士长
  • 技术积分: 802
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-08 21:45
文章分类

全部博文(36)

文章存档

2020年(1)

2017年(2)

2015年(1)

2014年(1)

2013年(1)

2012年(3)

2011年(27)

分类: Windows平台

2014-07-31 01:08:36

如下网上找到关于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";




阅读(4024) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~