m_shige1979のときどきITブログ

プログラムの勉強をしながら学習したことや経験したことをぼそぼそと書いていきます

Github(変なおっさんの顔でるので気をつけてね)

https://github.com/mshige1979

PerlでMouseモジュールとかいうのを使用してクラスを使用

Mouseを使用したクラスサンプル

cpanmを使用してMouseをインストール
[root@localhost pm_sample2]# cpanm Mouse

たくさんの関連モジュールをインストールとかコンパイルとか色々する

[root@localhost pm_sample2]#
sample.pl
#!/usr/bin/env perl

use strict;
use warnings;

use lib 'lib';

# テスト用のモデル
use Car;

print "静的なクラスメソッド実行\n";
print Car::test1() . "\n";

print "初期値未指定のインスタンスメソッド実行\n";
my $obj = new Car();
print $obj->name . "," . $obj->ago . "\n";
$obj->test2_01();

print "初期値指定のインスタンスメソッド実行\n";
my $obj2 = new Car(name => "aaaaa", ago => 50);
print $obj2->name . "," . $obj2->ago . "\n";
$obj2->test2_01();
lib/Car.pm
# モジュール
package Car {
    use Mouse;

    #
    has name => (
        is => "rw",         # rw:readwrite、ro:readonly
        isa => "Str",       # データ型、クラスも指定可能
        default => "",      # 初期値
        required => 0       # コンストラクタ作成時に必須
    );

    has ago => (
        is => "rw",
        isa => "Int",
        default => 0,
        required => 0
    );

    # これはクラスメソッド
    sub test1 {
        return "111";
    }

    # インスタンスメソッド
    sub test2_01{
        my ($self) = @_;

        print "name:" . $self->name . " ago:" . $self->ago . "desu \n";

    }

    # 一応これも
    __PACKAGE__->meta->make_immutable();

}

# モジュールの場合は指定
1;
結果
[root@localhost pm_sample2]# perl sample.pl
静的なクラスメソッド実行
111
初期値未指定のインスタンスメソッド実行
,0
name: ago:0desu
初期値指定のインスタンスメソッド実行
aaaaa,50
name:aaaaa ago:50desu
[root@localhost pm_sample2]#




継承

サブクラスとしてCar::BusにCarを継承

呼び出し
#!/usr/bin/env perl

use strict;
use warnings;

use lib 'lib';

# テスト用のモデル
use Car;

print "静的なクラスメソッド実行\n";
print Car::test1() . "\n";

print "初期値未指定のインスタンスメソッド実行\n";
my $obj = new Car();
print $obj->name . "," . $obj->ago . "\n";
$obj->test2_01();

print "初期値指定のインスタンスメソッド実行\n";
my $obj2 = new Car(name => "aaaaa", ago => 50);
print $obj2->name . "," . $obj2->ago . "\n";
$obj2->test2_01();

print "\nここから継承の機能\n\n";

# 継承
use Car::Bus;
print "静的なクラスメソッド実行\n";
print Car::Bus::test2() . "\n";

print "初期値未指定のインスタンスメソッド実行\n";
my $obj3 = new Car::Bus();
print $obj3->name . "," . $obj3->ago . "\n";
$obj3->test2_01();

print "初期値指定のインスタンスメソッド実行\n";
my $obj4 = new Car::Bus(name => "bbbbb", ago => 44);
print $obj4->name . "," . $obj4->ago . "\n";
$obj4->test2_02();
lib/Car.pm
# モジュール
package Car {
    use Mouse;

    #
    has name => (
        is => "rw",         # rw:readwrite、ro:readonly
        isa => "Str",       # データ型、クラスも指定可能
        default => "",      # 初期値
        required => 0       # コンストラクタ作成時に必須
    );

    has ago => (
        is => "rw",
        isa => "Int",
        default => 0,
        required => 0
    );

    # これはクラスメソッド
    sub test1 {
        return "111";
    }

    # インスタンスメソッド
    sub test2_01{
        my ($self) = @_;

        print "name:" . $self->name . " ago:" . $self->ago . "desu \n";

    }

    # 一応これも
    __PACKAGE__->meta->make_immutable();

}

# モジュールの場合は指定
1;
lib/Car/Bus.pm
# モジュール
package Car::Bus {
    use Mouse;
    use Car;

    extends 'Car';

    has sex => (
        is => "rw",
        isa => "Str",
        default => "man",
        required => 0
    );

    # これはクラスメソッド
    sub test2{
        return "222";
    }

    # 上書き
    sub test2_01{
        my ($self) = @_;

        print "この機能はオーバーライドされたことにしよう \n";

    }

    # インスタンスメソッド
    sub test2_02{
        my ($self) = @_;

        print "名前:" . $self->name . ", 歳:" . $self->ago . ", 性別:" . $self->sex ."です。 \n";

    }

    # 一応これも
    __PACKAGE__->meta->make_immutable();
}

# モジュールの場合は指定
1;
結果
[root@localhost pm_sample2]# perl sample2.pl
静的なクラスメソッド実行
111
初期値未指定のインスタンスメソッド実行
,0
name: ago:0desu
初期値指定のインスタンスメソッド実行
aaaaa,50
name:aaaaa ago:50desu

ここから継承の機能

静的なクラスメソッド実行
222
初期値未指定のインスタンスメソッド実行
,0
この機能はオーバーライドされたことにしよう
初期値指定のインスタンスメソッド実行
bbbbb,44
名前:bbbbb, 歳:44, 性別:manです。
[root@localhost pm_sample2]#

補足

継承は1つではなく複数のモジュールを継承することが可能
extendsに配列で定義することで対応可能

extends ('Car::Bus', 'Car::Bus2');

まとめ

Mouseなどである程度クラスをモダンな感じで書くことは出来そう。
元々オブジェクト指向に対応していないような感じだったからある程度の制限はつきそうだけどそのあたりはロジックで意識してコーディングする際に考えていくようにする。

気になることといえばインスタンスメソッドは継承などができているけど、クラスメソッドは継承できていない感じ