Software Engineering Lecture 5/16

Menu Menu


先週の復習


Reference in Perl

Perlのデータは、配列と[1,2,3]と連想配列{'a',1,'b',2} を使うことができる。
これらは、リスト(1,2,3)と違って無名配列(Anonymous Array) 、無名連想配列(Anonymous Hash)と呼ばれる。これらは名前がないので、直接$a{'test'}などというようには扱えない。実際には、これらは配列への参照であり、以下のように使う。

    pw071: {1} % perl5 -de 0
    Loading DB routines from perl5db.pl version 1
    Emacs support available.
    Enter h or `h h' for help.
    main::(-e:1):   0
      DB<1> @a = (1,2,3,4,5)
      DB<2> p "@a"
    1 2 3 4 5
      DB<3> @b = @a
      DB<4> p "@b"
    1 2 3 4 5
      DB<5> $a[2]="kono"
      DB<6> p "@a"
    1 2 kono 4 5
      DB<7> p "@b"
    1 2 3 4 5
      DB<8> $a = [1,2,3,4,5]
      DB<9> p $a
    ARRAY(0x805b3b4)
      DB<10> p @$a
    12345
      DB<11> p "@$a"
    1 2 3 4 5
      DB<12> $$a[1] = "kono"
      DB<13> p "@$a"
    1 kono 3 4 5
      DB<14> $b = $a
      DB<15> $$b[2] = "kakazu"
      DB<16> p "@$b"
    1 kono kakazu 4 5
      DB<17> p $b
    ARRAY(0x805b3b4)
      DB<18> p $b->[2] = "higa"
    higa
      DB<19> p "@$b"
    1 kono higa 4 5
      DB<20> $c = {}
      DB<21> $c->{'kono'} = 'teacher'
      DB<22> $c->{'higa'} = 'student'
      DB<23> p %$c
    higastudentkonoteacher
      DB<24> $c{'kono'} = 1
      DB<25> $c{'higa'} = 2
      DB<26> p keys %c
    higakono
      DB<27> p $c
    HASH(0x8134cc0)

プログラムの中に現れるPerlのデータは、\ を付けることによって参照を取ることができる。

  DB<28> $d  = \%c
  DB<29> p $d
    HASH(0x8152b00)
  DB<30> $d->{'shimabukuro'} = 'student'
  DB<31> p keys %c
    higashimabukurokono
  DB<32> 


問題

以下の例題を動かしてみて、Perlの参照の振る舞いを理解すること。出力を確認し、結果を提出する事。

     $a=[1,2,3,4];
     $a->[5]=3;
     print "@$a, $a->[2]\n";
     $b={};
     $b->{First}='Cat';
     $b->{Second}='Dog';
     $b->{Third}='Pig';
     foreach $key ( keys %$b)  { print "$key is $b->{$key}\n"  }
     @a =  ( 1,2,3,4);
     $refa = \@a;
     $refa->[5]=3;
     print "@$refa, $refa->[2]\n";


Package / Module

大規模なプログラムでは、変数や手続き名の数は数百以上になる。良く使われる語彙は500程度と言われているので、必然的に同じ名前を使うか、無意味な識別名を使う必要に迫られる。一方で、iとかjとかは一時変数として便利なので、良く使うことが多い。しかし一時変数などは、データフローを持つ構造化技法にはなじまない。

そこで名前空間というのを考える。名前空間が異なる場合は、そこでは同じ同じ字面でも異なる名前をさすことになる。名前空間は、パッケージ(Package)または、モジュール(Module)と呼ばれる。C では、static というキーワードによりファイルに局所的な名前を作成することができる。これにより疑似的な名前空間を作ることができる。

名前空間では、他の名前空間の名前を輸入(import) したり、自分の名前を公共的なものと宣言する(export)する機能がついていることが多い。しかし、名前空間と、その中の名前の対でアクセスすることでも十分である。これらの名前空間はセキュリティなどとからめて使われることも多いが (Java などはそうである)本来は、セキュリティと名前空間の概念は直交している。

Perl のpackage は、package Hogehoe; と記述することによって作られる。package 形式になったファイルは、hogehoge.pm という(Perl Module)拡張子をつける。これにより、use hogehoge; という形で Module を使用することができる。(通常のファイルは do "filename.pl"; というのを使う) ( perlmod を参照すること)


Object

オブジェクトのIDは、オブジェクトへのポインタあるいはユニークな識別子であり、データベースでのキーと同じ役目を果たす。しかし、オブジェクトのIDは普通はプログラマが直接指定することはない。

オブジェクトの間の関係は、

などが一般的だ。これらをさらに細かく、has-a, part-of などに分ける手法もあるが、オブジェクトとしての実現という視点から見ると、オブジェクトの属性(インスタンス変数)に代入されたオブジェクトID というだけだと言える。

オブジェクトの中身を直接いじることなく、オブジェクトIDを通してオブジェクトにアクセスすることにより、インタフェースと実装の分離を安全におこなうことができる。しかし、その分、実行は遅くなる。オブジェクトIDからメッソドを探すという操作が必要だからである。もし、メソッドを呼び出す時に、そのオブジェクトが何かを指定してやれば、そういうデメリットはない。C++などは、そういう発想で作られている。

継承関係は、あるオブジェクトからすべての属性を引き継ぎ、さらに何んらかの属性をつけ加えることを意味する。実際には、属性だけでなく、 オブジェクトの振る舞いもなんからの形で引き継いでいることをさす。ただし、今の所を、属性以外の条件はそれほど明確ではない。継承するオブジェクトのプログラム理論的な意味をすべて引き継ぐという考え方もあるが、それを厳密に行うのは実はかなりやっかいなことだし、実用的でもない。

データベースといっても、オブジェクトには一般的な検索方法は存在しない。もしデータベースが欲しければ、それは自分で実装しなくてはならない。(あるいは買ってきてもいいね)</p>


Object in Perl

Perlのオブジェクトは、Package と無名データを結び付けることによって作られる。( perlobj Perl のオブジェクト を参照すること、さらに、 perlbot Bag'o Object Tricks For Perl5 (the BOT) も見る方が良い。)

無名データをオブジェクトの持つ内部構造として、これにオブジェクトの操作方法を記述した Package を対応させると Perl のオブジェクトができあがる。この二つを結び付けるのが bless という演算子だある。

例えば猫のオブジェクトをPerlで記述すると、cat.pl のようになる。

    package Mammal;
    sub new {
	   my $type = shift;
	   my %params = @_;
	   my $self = {};
	   $self->{'Name'} = $params{'Name'};
	   $self->{'Sex'}  = $params{'Sex'};
	   $self->{'Weight'}  = $params{'Weight'};
	   $self->{'Color'}  = $params{'Color'};
	   bless $self, $type;
    }
    package Cat;
    @ISA = qw( Mammal );
    sub new {
	   my $type = shift;
	   my %params = @_;
	   my $self = Mammal->new(@_);
	   $self->{'Character'}  = $params{'Character'};
	   bless $self, $type;
    }

# method の書き方

  sub miyao {   my ($self,$arg) = @_;    $self->{Name} = $arg; }
  sub name_print {   my ($self) = @_;    print $self->{Name}; print "\n";}

# 使い方

 $a = Cat->new(Name=> Jackey, Sex=>F);
 print $a->{Name};print "\n";
 $a->name_print;

のようになる。


問題

上に出てきた猫に、methodを付けてみよ。method は package で宣言されるsubroutine で、インスタンス変数を変更したり、印刷したりする。まず、猫をたたくと怒るようにしてみよう。そして、怒ると鳴き声が変わるようにしてみよう。


カード

Perl5 で書いたカードの例題を見てみよう。

SimpleCard.pm SimpleCardPile.pm これらは、たとえば以下のようの使う。

    foreach $suit ('s','h','d','c') { 
       for($i=1;$i<14;$i++) { 
	 push(@card, CardPlay::SimpleCard->new(-suit=>$suit,-number=>$i)); 
       }
    } 
    $pile = CardPlay::SimpleCardPile->new(-contents=>\@card);
    $pile->print;
    $pile->shuffle;
    $pile->print;
    $pile->first->print;
    $pile->last->print;


宿題

SimpleCardPile.pm を使って、カードを配布して、五枚づつ、5人のユーザに配るプログラムを作成せよ。ポーカーの役の判定のプログラムをSimpleCardPile.pm に付加してみよ。

Perl の宿題は、メールでSubjectを

    Subject: Report on Software Engineering Lecture 5/16 

として提出すること。この講義の問題を提出する時には、
    Subject: Practice on Software Engineering Lecture 5/16

とすること。


Shinji KONO / Tue May 23 14:34:03 2000