10
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PerlAdvent Calendar 2018

Day 2

他の言語(Java)っぽくPerlを使う話

Last updated at Posted at 2018-12-01

この記事はPerl Advent Calendar 2018の2日目の記事です。

皆さん、PerlでOOPしてますか?
私は今年Perlに入門したのですが、Perlのオブジェクト指向はかなり独特だと感じました。
MouseやMooseを使って簡単に書くことはできますが、やはりそれでも他言語の構文との差はあるように思います。

そこで、Perlの柔軟な文法を活かしてclass構文を作ってみることにしました。

方針

  • できるだけJavaっぽくする
  • blessは裏側でやる
  • クラス名をクォートで囲わなくてはいけない箇所を減らす
  • 素のPerlよりも堅牢になる仕組みを組み込む

実装

https://github.com/yumlonne/p5-Class-JavaLike
突貫で作っていたためコード汚いです:bow:

現在実装できているのは以下の機能です

  • class構文
  • アクセス修飾子(public・protected・private)
  • 変数宣言(public var => @array)
  • コンストラクタ
  • メソッド
  • 引数型チェック
  • 単純な継承

使用例

use Class::JavaLike;
use Class::JavaLike::Classes;
use Types::Standard -types;

# classの定義
class Point2D => sub {
    # 変数の定義
    public var => qw(x y);

    # コンストラクタ
    public new => args[Int, Int] => returns[classes->Point2D] => constructor {
        my ($self, $x, $y) = @_;
        $self->x = $x;
        $self->y = $y;
        return $self;
    };

    # addメソッド
    public add => args[classes->Point2D] => returns[classes->Point2D] => method {
        my ($self, $that) = @_;
        return classes->Point2D->new($self->x + $that->x, $self->y + $that->y);
    };

    # プライベートなnegateメソッド
    private negate => args[] => returns[classes->Point2D] => method {
        my $self = shift;
        return classes->Point2D->new(-$self->x, -$self->y);
    };
};

こんな感じでclassを定義できます。
裏側では、パッケージClass::JavaLike::Class::${ClassName}にメソッド群を植え付けています。
このクラスは以下のように使えます。

# usage
my $p1  = classes->Point2D->new(10, 20);
my $p2  = classes->Point2D->new(22, 18);
my $res = $p1->add($p2);

say $res->x;    # -> 32
say $res->y;    # -> 38

classes->Point2Dは単に'Class::JavaLike::Class::Point2D'という文字列を生成しています。
同様のことがclassof('Point2D')でできますが、クォートが冗長だと思い、AUTOLOADを使ってクォート無しで指定できるようにしました。

また、継承ができるので、Point2Dを継承させてPoint3Dを作ることもできます。

class Point3D => extends Point2D => sub {
    public var => 'z';
    public new => args[Int ,Int ,Int] => returns[classes->Point3D] => constructor {
        my ($self, $x, $y, $z) = @_;
        $self->x = $x;
        $self->y = $y;
        $self->z = $z;
        return $self;
    };

    public add => args[classes->Point3D] => returns[classes->Point3D] => method {
        my ($self, $that) = @_;
        return classes->Point3D->new($self->x + $that->x, $self->y + $that->y, $self->z + $that->z);
    };
};

展望

戻り値の型チェックや再代入不能な変数(val)の導入などなど、Perlでのプログラミングを堅牢にする仕組みを導入できそうですね!
まだまだ未完成なので、今後も改善していきます。

最後に

Perlの文法を使い、何ができるか考えるのがすごく面白かったです。
みなさんもやってみてはいかがでしょうか。

明日は omokawa_yasu さんです!お楽しみに!!

10
1
1

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
10
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?