Perlのオブジェクト指向辺りの事を調べてみた

なかなか興味深い。
 

モジュールを定義する時のルール

ファイルの拡張子は"pm"。

pmじゃないと、useしたときに見つからなくてエラーが出る。

Can't locate TestClass1.pm in @INC (@INC contains: /usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi /usr/lib/perl5/site_perl/5.8.8 /usr/lib/perl5/site_perl /usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi /usr/lib/perl5/vendor_perl/5.8.8 /usr/lib/perl5/vendor_perl /usr/lib/perl5/5.8.8/i386-linux-thread-multi /usr/lib/perl5/5.8.8 .) at main1.pl line 3.
BEGIN failed--compilation aborted at main1.pl line 3.

 

最後で1を返さなければならない。

返さないと、こうなる。

TestClass1.pm did not return a true value at main1.pl line 3.
BEGIN failed--compilation aborted at main1.pl line 3.

 

クラス定義

TestClass1.pm

#!/usr/bin/perl

package TestClass1;
use strict;


sub new {
	my $class = shift;

	my $this = {
		x => 10,
		y => 20,
	};

	bless $this, $class;
}

sub show {
	my $this = shift;

	print "X: $this->{x}\n";
	print "Y: $this->{y}\n";
	print "----------\n";
}

sub addX {
	my $this = shift;
	my $add = shift;

	$this->{x} += $add;
}

1;

 
main1.pl

#!/usr/bin/perl

use TestClass1;


# インスタンス化
my $obj1 = new TestClass1;
#my $obj1 = TestClass1->new();  # これでもいい

# メソッド実行
$obj1->show();
my $x = $obj1->addX(30);
$obj1->show();

# sub内で最後に評価した値は勝手にreturnされる
print "return x: $x\n";

# インスタンス変数にはpublicでアクセス出来る
print "var x: $obj1->{x}\n";

 

実行結果
X: 10
Y: 20
----------
X: 40
Y: 20
----------
return x: 40
var x: 40

 

クラス変数を使う

TestClass2.pm

#!/usr/bin/perl

package TestClass2;
use strict;


# パブリッククラス変数
our $x = 10;
our $y = 20;


sub new {
	my $class = shift;

	my $this = {
	};

	bless $this, $class;
}

sub show {
	my $this = shift;

	print "X: $x\n";
	print "Y: $y\n";
	print "----------\n";
}

sub addX {
	my $this = shift;
	my $add = shift;

	$x += $add;
}

1;

 
main2.pl

#!/usr/bin/perl

use TestClass2;


my $obj2_1 = new TestClass2;
my $obj2_2 = new TestClass2;

# クラス変数を書き換え
$obj2_1->addX(30);
$obj2_1->show();
$obj2_2->show();

# クラス変数に直接アクセス
print "class var x: $TestClass2::x\n";

 

実行結果
X: 40
Y: 20
----------
X: 40
Y: 20
----------
class var x: 40

 

勝手にシングルトン

TestClass3.pm

#!/usr/bin/perl

package TestClass3;
use strict;


# プライベートクラス変数
my $ins;


sub new {
	my $class = shift;

	my $this = {
		x => 10,
		y => 20,
	};

	# まだ生成されていなかったら生成
	unless ($ins) {
		$ins = bless $this, $class;
	}
	$ins;
}

sub show {
	my $this = shift;

	print "X: $this->{x}\n";
	print "Y: $this->{y}\n";
	print "----------\n";
}

sub addX {
	my $this = shift;
	my $add = shift;

	$this->{x} += $add;
}

1;

 
main3.pl

#!/usr/bin/perl

use TestClass3;


# 普通にインスタンス化したつもりがシングルトン
my $obj3_1 = new TestClass3;
my $obj3_2 = new TestClass3;

$obj3_1->addX(30);
$obj3_1->show();
$obj3_2->show();

 

実行結果
X: 40
Y: 20
----------
X: 40
Y: 20
----------

 

newとblessの挙動

TestClass4.pm

#!/usr/bin/perl

package TestClass4;
use strict;


sub new {
	my $class = shift;
	print "new arg[0]: $class\n";
	'Hello!'
}

sub new1 {
	my $class = shift;
	print "new arg[0]: $class\n";
	bless {}, $class;
}

sub new2 {
	my $class = shift;
	print "new arg[0]: $class\n";
	bless {}, __PACKAGE__;
}

sub new3 {
	my $class = shift;
	print "new arg[0]: $class\n";
	bless {}, 'TestClass999';
}

sub show {
	my $this = shift;
	print "this: $this\n";
}

1;

 
main4.pl

#!/usr/bin/perl

use TestClass4;


my $obj1;

$obj1 = new TestClass4;
print "$obj1\n";
print "----------\n";

$obj1 = TestClass4->new();
print "$obj1\n";
print "----------\n";

$obj1 = TestClass4::new('TestClass4');
print "$obj1\n";
print "----------\n";

$obj1 = TestClass4->new1();
print "$obj1\n";
$obj1->show();
print "----------\n";

$obj1 = TestClass4->new2();
print "$obj1\n";
$obj1->show();
print "----------\n";

$obj1 = TestClass4->new3();
print "$obj1\n";
$obj1->show();

 

実行結果

クラスメソッドとして実行した場合は、第一引数はクラス名。
インスタンスメソッドとして実行した場合は、第一引数はクラスのインスタンス
newでクラスのインスタンスを返さなくてもいい。
存在しないクラスのインスタンスの生成は出来るけど、メソッドがないから普通のHashと同じ。

new arg[0]: TestClass4
Hello!
----------
new arg[0]: TestClass4
Hello!
----------
new arg[0]: TestClass4
Hello!
----------
new arg[0]: TestClass4
TestClass4=HASH(0x9947c28)
this: TestClass4=HASH(0x9947c28)
----------
new arg[0]: TestClass4
TestClass4=HASH(0x9947d0c)
this: TestClass4=HASH(0x9947d0c)
----------
new arg[0]: TestClass4
TestClass999=HASH(0x9947d3c)
Can't locate object method "show" via package "TestClass999" at main4.pl line 32.

 

クラスを継承する

TestClass5.pm

#!/usr/bin/perl

package TestClass5;
use strict;
use TestClass1;

@TestClass5::ISA = qw(TestClass1);

sub new {
        my $class = shift;

        my $this = new TestClass1;
        bless $this;
}

sub show {
        my $this = shift;

        # 継承元のメソッドを呼び出す
        $this->SUPER::show();
        print "++++++++++\n";
}

1;

 
main5.pl

#!/usr/bin/perl

use TestClass5;


# インスタンス化
my $obj5 = new TestClass5;
#my $obj5 = TestClass1->new();  # これでもいい

# メソッド実行
$obj5->show();
my $x = $obj5->addX(30);
$obj5->show();

# sub内で最後に評価した値は勝手にreturnされる
print "return x: $x\n";

# インスタンス変数にはpublicでアクセス出来る
print "var x: $obj5->{x}\n";

 

実行結果
X: 10
Y: 20
----------
++++++++++
X: 40
Y: 20
----------
++++++++++
return x: 40
var x: 40