クラス編
ということで、クラス。
Classで重要なのはやっぱり継承パターンと多態性でしょう。
アクセサはどうなってるのか、パッケージとかも含め、それくらいできると夢が広がりングな気がする
参考にはいつもの オブジェクト指向 / Perl逆引き事典 - サンプルコードによるPerl入門 を 見てます。
クラス作成
package が使えるそうな。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| use strict;
use warnings;
package Hoge;
sub new {
my $proto = shift;
my $self = {};
bless $self, $proto;
my $hoge = shift;
$self->{hoge} = $hoge;
return $self;
}
my $hoge = Hoge->new('hello world');
print $hoge->{hoge} . "\n";
|
コンストラクタの定義から、プロパティの設定と取得はこうやるのね。
元のページ → 汎用的なコンストラクタの雛形 - サンプルコードによるPerl入門 には init メソッドが必要とのことだったけど、今回は無視
どうやら、new のコンストラクタには [Class(prototype), arg1, arg2..]
といった形式で渡されているようですね
bless がよくわからないけど、js でいうところの Function.prototype.bind 的なものだろうか、第一引数に prototype を割り当てる的な(それだとapplyの方が近そうだけど)
プロパティ作成
もう少し、プロパティ
参考元を参考に、引数を色々受け取ってみる
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| use strict;
use warnings;
package Hoge;
sub new {
my $proto = shift;
my $self = {};
bless $self, $proto;
$self->init(@_);
return $self;
}
sub init {
my ($self, ($hoge, $foo, $bar)) = @_;
$self->{hoge} = $hoge;
$self->{foo} = $foo;
$self->{bar} = $bar;
}
my $hoge = Hoge->new('hello', 'world', 'perl #4');
# print $hoge->hoge . ':' . $hoge->foo . ':' . $hoge->bar . "\n";
## => Can't locate object method "hoge" via package "Hoge"
print $hoge->{hoge} . ':' . $hoge->{foo} . ':' . $hoge->{bar} . "\n";
|
なるほど、$self->{verialble}
で設定したものは、$self->variable
で取り出せないのね(Hashだから?)。当たり前といえば当たり前だった。
それ以外は意外とフツーな感じ
メソッド作成
プロパティまでは作成できたので、次はメソッド。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| use strict;
use warnings;
package Hoge;
sub new {
my $proto = shift;
my $self = {};
bless $self, $proto;
$self->init(@_);
return $self;
}
sub init {
my ($self, ($hoge, $foo, $bar)) = @_;
$self->{hoge} = $hoge;
$self->{foo} = $foo;
$self->{bar} = $bar;
}
sub greeting {
my $self = shift;
print $self->{hoge} . ':' . $self->{foo} . ':' . $self->{bar} . "\n";
}
my $hoge = Hoge->new('hello', 'world', 'perl #4');
$hoge->greeting();
|
先ほどの property で出力してたのを メソッドで。
第一引数に self(自分自身)
が入ってるとか、python ぽい
メソッド引数
メソッドのプロパティはどうなってるのか。
たぶん、#init
で試したから同じだと思うけど。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| use strict;
use warnings;
package Hoge;
sub new {
my $proto = shift;
my $self = {};
bless $self, $proto;
$self->init(@_);
return $self;
}
sub init {
my ($self, ($hoge, $foo, $bar)) = @_;
$self->{hoge} = $hoge;
$self->{foo} = $foo;
$self->{bar} = $bar;
}
sub greeting {
my $self = shift;
my ($arg1, $arg2, $arg3) = @_;
print $self->{hoge} . ':' . $self->{foo} . ':' . $self->{bar} . "\n";
print $arg1 . ',' . $arg2 . ',' . $arg3 . "\n";
}
my $hoge = Hoge->new('hello', 'world', 'perl #4');
$hoge->greeting('a', 'b', 'c');
|
ふむ。
shift は @_
から一つ shift して、 @_
自体は (a, b) = @_
とかのリスト構文的なので、値をまとめて代入できる。と
継承
クラスの継承。なんかちょっと特殊だった
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
| use strict;
use warnings;
package Hoge;
sub new {
my $proto = shift;
my $self = {};
bless $self, $proto;
$self->init(@_);
return $self;
}
sub init {
my ($self, ($hoge, $foo, $bar)) = @_;
$self->{hoge} = $hoge;
$self->{foo} = $foo;
$self->{bar} = $bar;
}
sub greeting {
my $self = shift;
my ($arg1, $arg2, $arg3) = @_;
print $self->{hoge} . ':' . $self->{foo} . ':' . $self->{bar} . "\n";
print $arg1 . ',' . $arg2 . ',' . $arg3 . "\n";
}
package Foo;
use base('Hoge');
sub new {
my $proto = shift;
my $self = {};
bless $self, $proto;
$self->init(@_);
return $self;
}
sub greeting {
my $self = shift;
print 'Im Foo#' . $self->{hoge} . ',' . $self->{foo} . "\n";
}
my $foo = Foo->new('hello', 'world', 'perl #4');
$foo->greeting('a', 'b', 'c');
|
まず、
@ISA
はよくわからなかったので、use base
による継承を使った。
super
を指定しないでも上位メソッドはコンストラクタから呼べた
new
のコンストラクタには、上位クラスの参照はなかった
- override 記述をしなくても、自動的に override だった。
- 上位プロパティは特に指定なしに呼び出せた。
これ、use で複数とか指定するとどうなっちゃうんだろ。差分継承だったらいいな。(それはいつかやる)
overrideしたメソッドから上位メソッドの呼び出し
疑問に思ったのでこれをやってみる
この方法は、ここから 参照。
ちなみに、やらんとしてることは、javascript だとこんな感じ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| var Hoge = function(a, b) {
this.a = a;
this.b = b;
};
Hoge.prototype.greeting = function (){
console.log('Im Hoge: ' + this.a + ',' + this.b);
};
var Foo = function(){
Hoge.apply(this, arguments);
};
Foo.prototype.greeting = function(bar){
Hoge.prototype.greeting.apply(this, arguments);
console.log('bar value => ' + bar);
};
var foo = new Foo('hello', 'world');
foo.greeting('**bar value**');
|
ということで、perl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
| use strict;
use warnings;
package Hoge;
sub new {
my $proto = shift;
my $self = {};
bless $self, $proto;
$self->init(@_);
return $self;
}
sub init {
my ($self, ($hoge, $foo, $bar)) = @_;
$self->{hoge} = $hoge;
$self->{foo} = $foo;
$self->{bar} = $bar;
}
sub greeting {
my $self = shift;
my ($arg1, $arg2, $arg3) = @_;
print $self->{hoge} . ':' . $self->{foo} . ':' . $self->{bar} . "\n";
print $arg1 . ',' . $arg2 . ',' . $arg3 . "\n";
}
package Foo;
use base('Hoge');
sub new {
my $proto = shift;
my $self = {};
bless $self, $proto;
$self->init(@_);
return $self;
}
sub greeting {
my $self = shift;
$self->SUPER::greeting('Im', 'Foo', '#greeting');
}
my $foo = Foo->new('hello', 'world', 'perl #4');
$foo->greeting('a', 'b', 'c');
|
なるほど。$self->SUPER::#method
で上位メソッド(というか親インスタンスのメソッドの呼び出し)ができるようになるのね。
これは使い道が広がるわ。
次回
アクセサを見てみたいところだけど、やっぱここで触れなかった package あたり。
どうやって分割してんのかと。