LoginSignup
12
4

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-12-02

この記事はモバイルファクトリー Advent Calendar 2017の2日目の記事です。
1日目に引き続き、@carimaticsが担当します。

1日目の記事は『Docker上でPerlのWebアプリケーションを動かしてみる』でした。

本記事では、Perlにおけるオブジェクト指向プログラミングの入門です。
オブジェクト指向プログラミング自体の入門ではありません。

開発環境

以下の環境で動作確認をしています。

  • OS: macOS Sierra version 10.12.6
  • Perl: perl v5.26.0
  • Carton: carton v1.0.28
  • Docker: Version 17.09.0-ce-mac35
    • Docker image: perl:5.26

本記事のコードは以下のコマンドで実行されるDockerコンテナで動かしました。

$ docker run -it perl:5.26 bash

準備

Cartonのインストール

Cartonがなければインストールします。

$ cpanm Carton

(中略)

7 distributions installed

$ carton --version
carton v1.0.28

作業ディレクトリの作成

適当なディレクトリを作成してそこに移動します。
/path/to/Work となっていますが、適宜読み替えてください

$ mkdir /path/to/Work
$ cd /path/to/Work

以下、本記事における「作業ディレクトリ」は、今作ったWorkディレクトリを指すとします。

依存モジュールのインストール

作業ディレクトリに以下の内容のcpanfileを作成します。

Work/cpanfile
requires 'Mouse';

依存モジュールをインストールします。

$ carton install

(中略)

Complete! Modules were installed into Work

Perlでオブジェクト指向プログラミングを実現する

もともとPerlはオブジェクト指向言語ではありません
しかし bless を駆使したり、CPANモジュールを利用したりすることでオブジェクト指向プログラミングが可能です。

本記事では、 Mouse というモジュールを用いてPerlにオブジェクト指向システムを導入します。

実行するスクリプトを Work/script 配下に、モジュールを Work/lib 配下に作成していきます。

Work/script 配下のスクリプトには、ファイルの先頭に以下の記述があるものとします。(冗長になるため、本文中では省略します)

use strict;
use warnings;
use utf8;
use feature qw/say/;
use lib 'lib';

クラス

Mouseを用いると、クラスの定義をすることができます。
xy平面上の点を表す Point クラスを定義してみましょう。

Work/lib/Point.pm
package Point {
    use Mouse;

    has x => (is => 'ro', isa => 'Int');
    has y => (is => 'ro', isa => 'Int');
};

1;

Mouse モジュールを use すると、そのパッケージを Mouse クラスにすることができます。
has name => parameters の構文で、属性(インスタンス変数)を定義します。
Point では、 xy 、という属性を定義しています。
パラメータはそれぞれ以下のような指定ができます。

  • is
    • ro (read only)、 rw (read/write)、 bare (何もしない)
  • isa
    • 変数に代入できる値の型を指定

今回は xy は両方ともread only( ro )かつ整数( Int )型となります。

では、 Point クラスを使ってみましょう。

Work/script/point.pl
use Point;

my $p = Point->new(x => 3, y => 4); # インスタンス生成
say "x: ", $p->x;
say "y: ", $p->y;

Mouseクラスのインスタンスは ClassName->new(parameters) で作成します。
また、引数で属性の初期化をすることができます。

実行してみます。

$ carton exec perl script/point.pl
x: 3
y: 4

継承

Mouseにも継承の仕組みがあり、あるクラスのサブクラスを作成することができます。
では、例とした先に作成した Point に色の情報を持たせた ColorPoint クラスを作成します。

Work/lib/ColorPoint.pm
package ColorPoint {
    use Mouse;

    extends qw/Point/;

    has color => (is => 'ro', isa => 'Str');
};

1;

extends でスーパークラスを指定できます。
Point クラスに color 属性を持たせたクラスが出来上がりました。
実行してみましょう。

Work/script/color_point.pl
use ColorPoint;

my $cp = ColorPoint->new(x => 2, y => 3, color => 'red');
say "x: ",     $cp->x;
say "y: ",     $cp->y;
say "color: ", $cp->color;
$ carton exec -- perl script/color_point.pl
x: 2
y: 3
color: red

isa による型チェックでは、指定されたクラスのサブクラスでもパスします。
2つの Point 間の距離を測る Ruler クラスを作成します。

Work/lib/Ruler.pm
package Ruler {
    use Mouse;

    has p1 => (is => 'rw', isa => 'Point');
    has p2 => (is => 'rw', isa => 'Point');

    sub distance {
        my $self = shift;

        my $dx = $self->p2->x - $self->p1->x;
        my $dy = $self->p2->y - $self->p1->y;

        return sqrt(($dx**2) + ($dy**2));
    }
};

1;

これは酷いコードですね!
しかし今は許容して話を進めます。

Ruler クラスは Point クラスの属性 p1p2 を持ち、それらのユークリッド距離を計算しています。

Work/script/ruler.pl
use Ruler;
use Point;
use ColorPoint;

my $p1 = Point->new(x => 0, y => 0);
my $p2 = ColorPoint->new(x => 3, y => 4, color => 'blue');

my $ruler = Ruler->new();
$ruler->p1($p1);
$ruler->p2($p2);

say "distance: ", $ruler->distance();

属性への値のセットはコンストラクタでも可能ですが、 $instance->attr(value) でも可能です。(read onlyでなければ)

$ carton exec -- perl script/ruler.pl
distance: 5

Rulerp2Point クラスのインスタンスを持つことができますが、そのサブクラス( ColorPoint )を持つこともできることを確認しました。

まとめ

Perlでもオブジェクト指向プログラミングができることを見ました。
has とか書くの面倒くさいですね。
この程度のコードであれば他の言語とそんなに変わらないのですが、オブジェクト指向プログラミングを言語レベルでサポートしているわけではないので、書いてて煩わしさを覚える場面は多々あります。
個人的な意見としては、オブジェクト指向プログラミングをしたいなら他の言語を選択すべきだと思ってます。

モバイルファクトリー Advent Calendar 2017は、3日目も引き続き @carimatics が担当します。
よろしくお願いします。

12
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
4