下記フォームに必要事項を入力後、確認ボタンを押してください。
元来、Perlのプログラミング手法は、一つ一つの処理に注目し、機能ごとに分割してプログラムをまとめていく構造化プログラミングが主流でした。構造化プログラミングの利点としては、同じ処理は関数を呼び出して何度も実行することができるため、簡潔な記述ができるという点にあります。しかし大規模なシステム構築に採用しようとするとデータ構造が複雑化し、プログラムのメンテナンスや修正が難しくなるという欠点があります。そこで新しく考案され注目されているプログラミングアプロ―チがオブジェクト指向プログラミングです。 オブジェクト指向プログラミングは構造化プログラミングとは異なり、オブジェクト指向プログラミングは、変数などのデータとメソッド、データを処理する手続きをオブジェクトというひとつのまとまりとして部品化し、それらを組み合わせていくプログラミング手法です。オブジェクト指向のプログラミングの考え方として、【抽象化】【カプセル化】【継承】【ポリモーフィズム】があります。【抽象化】はデータ抽象化と制御抽象化があり、データ抽象化はデータ構造を抽象化する型の定義づけを行うこと、制御抽象化はデータと切り離して動作の型の定義づけを行うことであり、オブジェクトを定義する構造や動作状態を型として定義することを意味します。【カプセル化】ではオブジェクト内部のデータや動作を隠蔽することを意味しオブジェクトの型を組み合わせによってデータの流れを別にすることでデータフローやプログラム構造を隠蔽するといった目的があります。【継承】はあるオブジェクトの特性を別のオブジェクトに引き継ぐことを意味し、親クラスである「スーパークラス」の特性を簡素なプログラムで新たなクラスが引き継ぐことで「スーパークラス」と同じ特性を持った新しい「サブクラス」として利用が可能になります。【ポリモーフィズム】は多様性、多態性とも呼ばれプログラミング言語の型システムの性質を複数の型にしてこれまでの【抽象化】【カプセル化】【継承】によって同じ名称のオブジェクトが別の動作、データの流れを行う動作をする多様性の性質を意味します。 これらのことによりプログラマーがオブジェクトを利用する際に、内部の構造やどのような処理が行われているのかといったことを意識する必要が少なくなります。このような利点から、オブジェクト指向プログラミングはコードの再利用生が向上することで大規模なシステム構築において大変有効的なプログラミング手法であるとされています。 Perlはオブジェクト指向性を備えて開発されたプログラム言語ではないため、C++ javaなどのようなデータ型としてのクラスは存在しません。Perlでクラスを作成するには変数やサブルーチンに名前空間を管理するためのペッケージに特殊な処理を行う必要があります。Perlでは一般的に関数のことをサブルーチンと呼ぶが、オブジェクト指向では関数のことを「メソッド」と呼んでいます。サブルーチンとメソッドの違いはメソッドの場合、暗黙のうちにオブジェクトそのものが第1引数として呼ばれる点です。つまりメソッドの第1引数は必ずオブジェクトのリファレンスとなりこの第1引数のことをインボカントと呼んでいます。
オブジェクト指向プログラミンでは実際に存在するものと同じものをとらえて抽象化を行っていきます。そこで使われる【クラス】の考え方は共通の性質を持ったオブジェクトの集合でありそのデータ型を定義すること、オブジェクトというのは実際に値を設定した実体のことでありインスタンスとも呼ばれています。perlのプログラムではクラスは他の言語と異なりパッケージの別名のように扱われています。実際、Perlでクラスを作成するにはパッケージを作成することから始めます。 package car; このように宣言します。クラスとパッケージの違いはクラスには「コンストラクタ」という特殊なメソッドを定義する必要があるという点でしょう。コンストラクタとは、新しいオブジェクトが生成されるときに呼び出される特殊なメソッドのことを呼びます。簡単に言えば新しく生成したクラスを呼び出すためのメソッドのことです。Perlではコンストラクタには任意の名前をつけることができるが、一般的には[new]という名前が使われておりここでは「new」を使ってコンストラクタを定義します。コンストラクタもクラスのメソッドのひとつなので、第1引数にクラスのリファレンス(インボカント)が渡されます。
sub new { my $class=shift; }次にオブジェクトを用意します。perlではオブジェクトにスカラー、配列、ハッシュといったあらゆる型の変数を使用します。
my $self ={ name=>"soralis", body=>"metal", };最後に定義したクラスに先ほど作成した変数を関連付ける作業を行います。クラスに作成した変数を関連付けるにはbless関数を使用します。 bless関数は二つの引数が必要です。第1引数に[関連付けたい変数のリファレンス]、[第2引数に関連づけるクラス名]を指定します。
bless $self,$class;$selfをblessすることによって、クラスのオブジェクトとして関連付けされます。オブジェクトの作成から、blessされたオブジェクトのリファレンスを返すまでの作業を一般的にコンストラクタで行っていきます。先ほど定義したcatクラスのコンストラクタは以下のとおりです。
sub new{ my $class=shift; #オブジェクトを用意 my $self ={ name=>"soralis", body=>"metal", }; #blessする bless $self,$class; return $self; }これがクラスを定義する一連の流れです。定義したクラスを使用するには[use パッケージ名」で使用するクラスを宣言しなければなりません。 use car; 次にクラスのオブジェクトを作成していきます。オブジェクトを作成するにはクラスで定義したコンストラクタを使います。 my $car =new car; これにより$catにはcatクラスのオブジェクトのリファレンスが入ります。catクラスのメソッドやプロパティにアクセスするには「->(アロー演算子)」で実行します。 $car->{name} #carクラスのnameプロパティ $car->{body} #carクラスのbodyメソッド
package car; #コンストラクタ sub new{ my $class =shift; ##オブジェクト my $self={ name=>"soralis", body=>"metal", speed=>"60km", }; return bless $self,$class; } #eatメソッド sub run{ #インボカント my $self =shift; print "$self->{name}が $self->{speed}で走る。\n"; } 1;
オブジェクト指向プログラミングにおいて「継承」とは、ある既存のクラスをベースにして、新しく別のクラスを定義することです。ベースとなるクラスは「スーパクラス」、新しく定義したクラスを「サブクラス」と呼ビサブクラスにはスーパークラスのメソッドなどの性質が引き継がれるため、スーパークラスとは異なる部分を定義するだけですむためコードの再利用率が高まります。Perlでクラスを継承するには、@ISAという配列に継承したいクラス名を宣言します。@ISA配列を使ってクラスを継承する場合には、useであらかじめスーパークラスを宣言しておく必要があります。 次の例文ではあらかじめsuperclass,Subclassというパッケージを定義して、ubclass.pm内で@ISA配列を使いSuperClassを継承させています。subclassのみを呼び出し、SubClass内のメソッドを使用すると共に、SubClass.pmで継承したSuperClass内のメソッドSuper_methodを使用しています。
package SuperClass; use strict; #コンストラクタ sub new{ my($class,%args)=@_; #オブジェクト my $self=bless{},$class; $self->init(%args); return $self; } #メソッド sub super_method{ my $self=shift; print "SuperClassで定義されているメソッド\n"; } 1; #$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#
package SubClass; use SuperClass; use strict; our(@ISA); @ISA=qw(SuperClass); sub init{ my($self,%args)=@_; $self->{name}=$args{name}; $self->{job}=$args{job}; } sub get_name{ my $self=shift; return $self->{name}; } sub get_job{ my $self=shift; return $self->{job}; } 1; ############################################################
#!/usr/bin/perl use lib qw(./); use SubClass; use strict; my $subclass=new SubClass(name=>"太郎",job=>"プログラマー"); #サブクラスのメソッド print "サブクラスのメソッドを使用\n"; print "名前:".$subclass->get_name. "\n"; print "職業:".$subclass->get_job. "\n"; #スーパークラスのメソッド print "スーパークラスのメソッドを使用\n"; #メソッドが継承されている $subclass->super_method; #############################################################
Perlでクラスの継承を行うには、@ISA配列を使う以外に、[baseプラグマモジュール]を使用して継承を実行することができます。@isa配列を使って継承を行うと、あらかじめスーパークラスをuseしておかなければなりません。baseプラグマモジュールを使用すると、スーパークラスをuseする必要がないので、ソースが簡潔になります。@ISA配列とbaseプラグマのソース比較は次のとおりです。 [@ISA]
use SuperClass; our(@ISA); @ISA=qw(SuperClass);[base]
use base qw(SomeClass);
package SubClass; use strict; use base qw(SuperClass); sub init{ my($self,%args)=@_; $self->{name}=$args{name}; $self->{job}=$args{job}; } sub get_name{ my $self=shift; return $self->{name}; } sub get_job{ my $self=shift; return $self->{job}; } 1; #############################################################
Package SuperClass; use strict; sub new{ my($class,%args)=@_; my $self=bless {},$class; $self->init(%args); return $self; } sub super_method{ my $self=shift; print "SuperClassで定義されているメソッドです。\n"; } 1; ############################################################
#!/usr/bin/perl use lib qw(./); use SubClass; use strict; my $subclass=new SubClass(name=>"太郎",job=>"プログラマー"); #サブクラスのメソッド print "サブクラスのメソッドを使用\n"; print "名前:". $subclass->get_name ."\n"; print "職業:".$subclass->get_job ."\n"; #スーパークラスのメソッド print "スーパークラスのメソッドを使用\n"; #スーパークラスのメソッドが継承されている $subclass->super_method;
使用するクラスに指定したメソッドが宣言されているかどうか調べるために、Perlではcanメソッドが用意されています。canメソッドはクラスを定義すると自動的に使用できるようになるので、プログラマーがクラス内にメソッドとして定義する必要はありません。can メソッドは以下のように使用します。
$class->can('method_name');定義したクラスのオブジェクトのcanメソッドを呼び出します。canメソッドはメソッド名を引数に持ちます。
#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$# #!/usr/bin/perl use lib qw(./); use Man; use strict; my $man =new Man(name=>"一郎"); #get_nameメソッドが定義されているかどうか if($man->can("get_name")){ print "get_nameは定義されている\n"; print "名前:". $man->get_name ."\n\n"; }else{ print "get_nameは定義されていません\n"; } #get_jobメソッドが定義されているかどうか if($man->can("get_job")){ print "get_jobは定義されています。\n"; print "名前:". $man->get_job ."\n\n"; }else{ print "get_jobは定義されていません\n"; } #$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#$#
package Man; use strict; sub new{ my($class,%args)=@_; my $self=bless{},$class; $self->{name}=$args{name}; $self->{job}=$args{job}; return $self; } #get_nameメソッド sub get_name{ my $self=shift; return $self->{name}; } 1; ###################################################################
定義しているクラスがあるクラスを継承しているかどうか調べるために、Perlではisaメソッドが用意されている。isaメソッドもcanメソッドと同じくクラスを定義すると自動的に使用することができるメソッドなので、ユーザーがクラス内に定義する必要はありません。
################################################################## package SuperClass; use strict; sub new{ my($class,%args)=@_; my $self=bless {},$class; $self->init(%args); return $self; } sub super_method{ my $self=shift; print "SuperClassで定義されているメソッドです。\n"; } 1; ################################################################
package SubClass; use base qw(SuperClass); use strict; sub init{ my($self,%args)=@_; $self->{name}=$args{name}; $self->{job}=$args{job}; } #get_nameを定義 sub get_name{ my $self=shift; return $self->{name}; } #get_jobを定義 sub get_job{ my $self=shift; return $self->{job}; } 1; #############################################################
package OtherClass; use strict; sub new{ my($class,%args)=@_; return bless{},$class; } #other_methodを定義 sub other_method{ my $self=shift; print "OtherClassで定義されているメソッドである\n"; } 1; ###########################################################
#!/usr/bin/perl use lib qw(./); use SubClass; use OtherClass; use strict; #SubClassのオブジェクト; my $subclass=new SubClass(name=>"太郎",job=>"サッカー選手"); #OtherClassのオブジェクト my $otherclass=new OtherClass; #SubClassはSuperClassを継承しているか。 #isaメソッドでクラス継承を確認する if($subclass->isa("SuperClass")){ print "SubClassはSuperClassを継承しています。\n"; }else{ print "SubClassはSuperClassを継承していません。\n"; } #OtherClassはSuperClassを継承しているか if($otherclass->isa("SuperClass")){ print "OtherClassはSuperClassを継承しています。\n"; }else{ print "OtherClassはSuperClassを継承していません。\n"; }
Exporterモジュールはパッケージの名前空間に対してエクスポートするものを制御するためのモジュールです。Exporterモジュールにはクラス内のメソッドを呼び出すための以下のような特殊変数が用意されています。
● @EXPORT | 指定したメソッドや変数を自動的にインポートします。 |
● @EXPORT_OK | 指定したメソッドや変数を呼び出し明示的に指定する必要があります。 |
● @EXPORT_FAIL | 指定したメソッドや変数をインポート不可にします。 |
● @%EXPORT_TAGS | 指定したメソッドや変数は呼び出し側で指定したハッシュのキーに応じてインポートします。 |
################################################################################## package MyPackage; use Exporter; our(@EXPORT,@EXPORT_OK,%EXPORT_TAGS,@ISA); @ISA=qw(Exporter); #自動的に呼び出し可能なサブルーチン @EXPORT=qw(function1); #明示的に指定して呼び出し可能なサブルーチン @EXPORT_OK=qw(function2 function3); #キーを指定で呼び出し可能なサブルーチン %EXPORT_TAGS=(TEST=>[qw(function3)]); sub function1{ print "function1です。\n"; } sub function2{ print "function2です。\n"; } sub function3{ print "function3です。\n"; } sub function4{ print "function4です。\n"; } #################################################################################
#!/usr/bin/perl use lib qw(./); use MyPackage; #自動的に呼び出し function1(); #################################################################################
#!/usr/bin/perl use lib qw(./); use MyPackage qw(function2); #明示的に呼び出し function2(); #################################################################################
#!/usr/bin/perl use lib qw(./); use MyPackage qw(:TEST); #キーを指定して呼び出し function3(); #################################################################################
#!/usr/bin/perl use lib qw(./); use MyPackage; #@EXPORT変数に指定していない場合はパッケージ修飾子から記述しないとエラー MyPackage::function4(); #################################################################################
クラスを定義する際にコンストラクタや変数の設定などを記述していると、複雑なコードになってしまいます。たとえば定義するクラスが値を保持しておくためだけのような簡単なもので、今後スーパークラスとして使用されることがないのであれば、Class:Structモジュールを使用することで、クラスの初期化などの作業を簡素化することができます。Class::Structモジュールはstructサブルーチンのみをエクスポートします。structサブルーチンは定義するクラスに必要なプロパティを定義することができますがClass::Structはクラス設計やプロパティ操作に特化したモジュールではありません。必要なデータの集まりをstructサブルーチンで定義しているだけです。
################################################################################# package MyPackage; use strict; sub new{ my($class,%args)=@_; my $self=bless{},$class; $self->{name}=$args{name}; $self->{jobs}=$args{jobs}; $self->{hobby}=$args{hobby}; $self->{favorite}=$args{favorite}; return $self; } sub name{ my($self,$name)=@_; if($name){ $self->{name}=$name; } return $self->{name}; } sub hobby{ my($self,$hobby)=@_; if($hobby){ $self->{hobby}=$hobby; } return $self->{job}; } sub favorite{ my($self,$favorite)=@_; if($favorite){ $self->{favorite}=$favorite; } return $self->{favorite}; } 1; ##################################################################################
package StructTest; use Class::Struct; use strict; struct( name=>'$', job=>'$', hobby=>'$', favorite=>'$' ); 1; ###################################################################################
#!/use/bin/perl use lib qw(./); use StructTest; use MyPackage; use strict; my $structtest=new StructTest( name=>"太郎", job=>"営業", hobby=>"音楽鑑賞",favorite=>"コーンスープ" ); print "StructTest モジュールの結果:\n"; print "名前:".$structtest->name ."\n"; print "職業:".$structtest->job . "\n"; print "趣味:".$structtest->hobby ."\n"; print "好きなもの" .$structtest->favorite ."\n\n"; #値を変更 $structtest->job("事務職"); $structtest->hobby("読書"); $structtest->favorite("味噌汁"); print "値を変更しました。\n"; print "名前:".$structtest->name ."\n"; print "職業:".$structtest->job ."\n"; print "趣味:".$structtest->hobby ."\n"; print "好きなもの:" .$structtest->favorite. "\n\n"; print "―" x 20 . "\n\n"; my $mypackage =new MyPackage( name=>"太郎", job=>"営業", hobby=>"音楽鑑賞", favorite=>"ラーメン" ); print "MyPackageモジュールの結果:\n"; print "名前:".$mypackage->name ."\n"; print "職業:".$mypackage->job ."\n"; print "趣味:".$mypackage->hobby."\n"; print "好きなもの:".$mypackage->favorite."\n"; ####################################################################################
Class::Accessorモジュールを使用してクラスを作成すると、プロパティと同じ名前のアクセサメソッドを簡単に作成できます。Class::Accessorのmk_accessorsサブルーチンでアクセサメソッドを作成したいプロパティを指定し、指定されたプロパティはアロー演算子を使用してアクセスすることができます。
PerlにはJavaやPHP(Version5から)のようなメソッド、プロパティのアクセス制御があります。Perでpublic(クラス内、またはクラス外からのアクセスが可能)、private(そのクラス内のみアクセス可能)を実装するにはClass::Declareを使用します。Class::Declareを継承し、Class::Declareのdeclareメソッドにpublic,privateにするプロパティを指定します。privateで宣言したプロパティ、メソッドをそのクラス以外で使用するとエラーになります。
############################################################################################################## package DeclareTest; use strict; use base qw(Class::Declare); #Class::Declare _PACKAGE_->declare( public=>{public_var=>"publicです。"}, private=>{priuvate_var=>"privateです。"} ); sub public_method{ my $self=_PACKAGE_->public(shift); print "publicメソッドである\n"; } sub use_private_method{ my $self=_PACKAGE_->public(shift); print "publicメソッドを介してのprivateメソッド使用はok\n"; $self->private_method; } sub private_method{ my $self=_PACKAGE_->private(shift); print "privateメソッドである\n"; } 1;
################################################################################################# #!/usr/bin/perl use lib qw(./); use DeclareTest; use strict; my $declaretest=new DeclareTest; #public print "Public:".$declaretest->public_var."\n"; #値を変更 $declaretest->public_var("値を変更した"); print "public_varの値を変更:".$declaretest->public_var ."\n"; ##メソッドを使用 $declaretest->public_method; $declaretest->use_private_method; #priovateで宣言しているものは直接使用できない。 print "private:" .$declaretest->private_var."\n"; $declaretest->private_method; ##################################################################################################