1. Perl
  2. オブジェクト指向
  3. 入門

Perlオブジェクト指向プログラミング入門

Perlオブジェクト指向プログラミングの入門記事です。

クラスの定義

Perlではクラスの定義はpackageを使って行います。

package Point;

コンストラクタ

コンストラクタであるnewというクラスメソッドを定義します。bless関数を使って、オブジェクトを生成します。

package Point;

sub new {
  my $class = shift;
  
  # オブジェクトの生成
  my $self = bless {@_}, $class;
  
  # 初期化処理
  
  return $self;
}

コンストラクタを定義すれば、オブジェクトを作成することができます。

my $point = Point->new;

newメソッドは、ハッシュを受け取ることができます。

my $point = Point->new(x => 1, y => 2);

この値は、フィールドに設定されます。

初期化処理

コンストラクタでの初期化処理は以下のように書きます。

sub new {
  my $class = shift;
  
  # オブジェクトの生成
  my $self = bless {@_}, $class;
 
  # 初期化処理
  $self->{x} //= 0;
  $self->{y} //= 0;

  return $self;
}

//演算子を使って初期化しています。

アクセッサ

次にアクセッサを定義してみましょう。アクセッサとはフィールドにアクセスするためのメソッドのことです。アクセッサを定義すれば、フィールドにアクセスすることができます。

# xを取得・設定するアクセッサ
sub x {
  my $self = shift;
  
  if (@_) {
    $self->{x} = $_[0];
    return $self;
  }
  
  return $self->{x};
}

アクセッサを定義するとフィールドにアクセスすることができます。

# 値の設定
$point->x(1);

# 値の取得
my $x = $point->x;

継承

継承を行うにはbaseモジュールを使います。Pointを継承したPoint3Dを作ってみましょう。

package Point3D;

use base 'Point';

スーパークラスのメソッドの呼び出し

SUPER疑似クラスを使って、スーパークラスのメソッドを呼び出すことができます。

package Point3D;
use base 'Point';

# ...

sub clear {
  my $self = shift;
  
  # スーパークラスのclearメソッドの呼び出し
  $self->SUPER::clear;
}

コンストラクタのオーバーライド

サブクラスでコンストラクタをオーバーライドしたい場合があると思います。コンストラクタをオーバーライドするには次のようにします。

package Point3D;
use base 'Point';

sub new {
  my $class = shift;
  
  my $self = $class->SUPER::new(@_);
  
  # 初期化処理
  $self->{z} //= 0;

  return $self;
}

newはコンストラクタなので必ずオブジェクト自身を返すようにします。

クラスの作成 - 実践編

Perlのオブジェクト指向プログラミングを実践してみましょう。PointクラスとPoint3Dクラスを作成してみます。

Pointクラス

  • Pointは点を表すクラスです。
  • xとyというフィールドがあり、アクセッサを持ちます。
  • xとyの値を0にクリアするclearというメソッドを持ちます。
package Point;

sub new {
  my $class = shift;
  
  # オブジェクトの生成
  my $self = bless {@_}, $class;
 
  # 初期化処理
  $self->{x} //= 0;
  $self->{y} //= 0;

  return $self;
}

# xを取得・設定するアクセッサ
sub x {
  my $self = shift;
  
  if (@_) {
    $self->{x} = $_[0];
    return $self;
  }
  
  return $self->{x};
}

# yを取得・設定するアクセッサ
sub y {
  my $self = shift;
  
  if (@_) {
    $self->{y} = $_[0];
    return $self;
  }
  
  return $self->{y};
}

sub clear {
  my $self = shift;
  
  $self->x(0);
  $self->y(0);
}

1;

末尾に「1;」という記述があるのは、モジュールを書くファイルの末尾が真でなければならないというルールがあるためです。

Pointクラスは以下のように使用することができます。

use Point;
my $point = Point->new(x => 3, y => 5);
print $point->x;
$point->y(9);
$point->clear;

Point3Dクラス

  • Point3Dは3次元の点を表すクラスです。
  • x,y,zというフィールドがあり、アクセッサを持ちます。
  • x,y,zの値を0にクリアするclearというメソッドを持ちます。

Point3DPointを継承して作成します。clearメソッドはxyzの値をクリアするためにオーバーライドされています。

package Point3D;
use base 'Point';

# zを取得・設定するアクセッサ
sub z {
  my $self = shift;
  
  if (@_) {
    $self->{z} = $_[0];
    return $self;
  }
  
  return $self->{z};
}

sub clear {
  my $self = shift;
  
  $self->SUPER::clear;
  
  $self->z(0);
}

1;

Point3Dクラスは以下のように利用することができます。

use Point3D;
my $point = Point->new(x => 3, y => 5, z => 8);
print $point->z;
$point->z(9);
$point->clear;

実行できるサンプル

実行できるサンプルを書いておきますね。

lib/Point.pm

libというディレクトを作成して、その中にPoint.pmというファイルを作成してください。

package Point;

use strict;
use warnings;

sub new {
  my $class = shift;
  
  # オブジェクトの生成
  my $self = bless {@_}, $class;
 
  # 初期化処理
  $self->{x} //= 0;
  $self->{y} //= 0;

  return $self;
}

# xを取得・設定するアクセッサ
sub x {
  my $self = shift;
  
  if (@_) {
    $self->{x} = $_[0];
    return $self;
  }
  
  return $self->{x};
}

# yを取得・設定するアクセッサ
sub y {
  my $self = shift;
  
  if (@_) {
    $self->{y} = $_[0];
    return $self;
  }
  
  return $self->{y};
}

sub clear {
  my $self = shift;
  
  $self->x(0);
  $self->y(0);
}

1;

lib/Point3D.pm

libというディレクトの中にPoint3D.pmというファイルを作成してください。

package Point3D;
use base 'Point';

# zを取得・設定するアクセッサ
sub z {
  my $self = shift;
  
  if (@_) {
    $self->{z} = $_[0];
    return $self;
  }
  
  return $self->{z};
}

sub clear {
  my $self = shift;
  
  $self->SUPER::clear;
  
  $self->z(0);
}

1;

object.pl

クラスを読み込んで利用するサンプルです。libモジュールを使うことで、モジュールの検索パスを追加できます。

use strict;
use warnings;
use lib 'lib';
use Point3D;

my $point = Point3D->new(x => 3, y => 5, z => 8);

print $point->z . "\n";

$point->z(9);

print $point->z . "\n";
$point->clear;

print $point->z . "\n";

スクリプトの実行

ディレクトリ構成は以下のようにします。

object.pl
lib - Point.pm
    - Point3D.pm

以下のように実行してください。

perl object.pl

出力結果です。

8
9
0

オブジェクト指向プログラミングの詳細

オブジェクト指向プログラミングの詳細については、以下の記事を見てください。

業務に役立つPerl

Perlテキスト処理のエッセンス 書籍版

関連情報