Drkcore

09 06 2008 perl Moose Tweet

MooseでVisitorパターン

本に忠実な感じで、visitorクラスを。

ProductName 増補改訂版Java言語で学ぶデザインパターン入門
結城 浩
ソフトバンククリエイティブ / ¥ 3,990 ()
通常24時間以内に発送

package Visitor;
use Moose::Role;
requires 'visit';

package ListVisitor;
use Moose;
use Perl6::Say;
with 'Visitor';

sub visit {
  my ($self, $entry) = @_;
  my $currentdir = "";
  if(ref($entry) eq "File"){
    say $currentdir . "/" . $entry->toString();
  }
  elsif (ref($entry) eq "Directory"){
    say $currentdir . "/" . $entry->toString();
    my $savedir = $currentdir;
    $currentdir = $currentdir . "/" . $entry->getName();
    my $it = $entry->iterator();
    while($it->has_next){
      my $e = $it->next;
      $e->accept($self);
    }
    $currentdir = $savedir;
  }
}

package Element;
use Moose::Role;
requires 'accept';

package Entry;
use Moose::Role;
use Perl6::Say;
with 'Element';
requires 'getName';
requires 'getSize';


sub add {say "method add";}
sub iterator {say "method iterator";}

sub toString {
  my $self = shift;
  return $self->getName() . " (" . $self->getSize() . ")";
}

package File;
use Moose;
with 'Entry';

has name => (isa => 'Str', is => 'rw');
has size => (isa => 'Int', is => 'rw');

sub getName {
  my $self = shift;
  return $self->name;
}

sub getSize {
  my $self = shift;
  return $self->size;
}

sub accept {
  my ($self,$v) = @_;
  $v->visit($self);
}

package Directory;
use Moose;
use MooseX::Iterator;
with 'Entry';
has name => (isa => 'Str', is => 'rw');
has directory  => (isa => 'ArrayRef', is => 'rw', default => sub{[]});

sub getName {
  my $self = shift;
  return $self->name;
}

sub getSize {
  my $self = shift;
  my $size = 0;
  my $it = $self->iterator();
  while ( $it->has_next ) {
    my $e = $it->next;
    $size += $e->getSize();
  }
  return $size;
}

sub add {
  my ($self, $entry) = @_;
  push @{$self->directory}, $entry;
  return $self;
}

sub iterator {
  my $self = shift;
  return MooseX::Iterator::Array->new( collection => $self->directory );
}

sub accept {
  my ($self,$v) = @_;
  $v->visit($self);
}

package main;
use Perl6::Say;

say "Making root entries";
my $rootdir = Directory->new( name => "root" );
my $bindir = Directory->new( name => "bin" );
my $tmpdir = Directory->new( name => "tmp" );
my $usrdir = Directory->new( name => "usr" );
$rootdir->add($bindir);
$rootdir->add($tmpdir);
$rootdir->add($usrdir);

my $vi = File->new( name => "vi", size => 10000 );
my $latex = File->new( name => "latex", size => 20000 );
$bindir->add($vi);
$bindir->add($latex);
my $visit = ListVisitor->new();
$rootdir->accept($visit);

実行

Making root entries
/root (30000)
/bin (30000)
/vi (10000)
/latex (20000)
/tmp (0)
/usr (0)

javaのコードだとvisitメソッドをオーバーロードしてんだけどMooseでもできるのかどうかはわからなかった。

withとextendsの使い分けが微妙にわかってなさげ。このパターンだとsuperが必要ないからか?

directryクラスでのみ必要なメソッドは抽象クラスでエラーにしたい場合どうすべきかちょっとわからない。

About

  • もう5年目(wishlistありマス♡)
  • 最近はPythonとDeepLearning
  • 日本酒自粛中
  • ドラムンベースからミニマルまで
  • ポケモンGOゆるめ

Tag

Python Deep Learning javascript chemoinformatics Emacs sake and more...

Ad

© kzfm 2003-2021