すぐわかる オブジェクト指向 Perl 第12章 演算子のオーバーロード
おぉ
- 前章で作ったセッターとゲッターをひとつのサブルーチン(メソッド)にまとめる。
- セッターかゲッターかは、呼ばれた時の引数の数で判断する
- かっこいい!無駄が無い!クール!
うおお・・・
- 演算子のオーバーロードで、同じオブジェクトでも別な内容を応答する、という例題
- 数字を期待されているのか、文字列を期待されているのか、というのをオブジェクト自体が判断して適切な値を返す、ようにオーバーロードを設定する
- 正直、自信無い、凄すぎる・・・
use overload '""' => "toString", '0+' => "toNumber"; sub toString { my $self = shift; my $a = $self->{a}; my $b = $self->{b}; my $c = $self->{c}; return ("($a,$b,$c)"); } sub toNumber { my $self = shift; return ($self->{s}); }
- 抜粋して書くとこう。
- うん、正直使いこなせる気がしねぇ・・・
すぐわかる オブジェクト指向 Perl 第11章 オブジェクト クラスの作成
-> は左結合
- なるほど
$space = Triangle->new(3,4,5)->InscribedCircleSpace;
- この場合には、Triangleメソッドに 3 , 4 , 5 って値を与えて三角形オブジェクトを作成して、その内接円を求める
- おぉ、なんかかっこいい
!?
一方、クラスは型のことです。
少年漫画「翔丸」(能條純一著、講談社刊)では、さっきまで無軌道に暴れていた怖いお兄さん達が、謎の美少年・翔丸によってナイフで傷を付けられる事によってすっかり型にはめられてしまい、軒並み「翔丸組」の軍門に下ってしまいます。
- いきなりの能條画伯の登場にビビる
- 次のページにワンカットもある
- こんな展開を550ページの本の350ページまで隠しておくとは・・・
- 翔丸 - Wikipedia
『翔丸』(しょうまる)は、能條純一による日本の漫画。『コミックモーニング』(講談社)において1987年13号から1989年6号に掲載された。当初は不定期掲載、のちに隔週連載。同じく能條の『天の男』や『ゴッドハンド』に見られる「悪のカリスマ」を描いた系統の作品である。
- 知らないなぁ・・・
- 絶版本を置いているマンガ図書館Zには無かった。漫画喫茶ならあるかな?
- わかんねぇ・・・けど、分かるような・・・
- ナイフでシャってやる事でクラスを作る、的な?
クラスとオブジェクトの関係はよく人形焼きに例えられます。人形焼きというと鯛焼きとかペコちゃん焼きの仲間で、皮とアンコを型に入れて焼くと、中から七福神などの形をしたお菓子が出てきます。
ここで人形焼きを作る機械をコンストラクタ、いっこいっこの人形焼きをオブジェクトというわけです。
- こちらは分かる。
- クラス、オブジェクト、コンストラクタ
オブジェクトは、あるクラスのコンストラクタによって、そのクラスのオブジェクトとして生成される
- ううん、わかったような。
- 鯛焼きは、鯛焼き機によって、鯛焼きになる・・・?んん?
# クラスとインスタンスとオブジェクト
クラスもまたオブジェクトである
- なるほど、先の「鯛焼きは、鯛焼き機によって、鯛焼きになる」で??ってなったのは、こういうことか?
クラスがオブジェクトに与える要素のことをプロパティ(property 属性)といいます
メソッドは、オブジェクトに渡すメッセージであるという言い方をしましたが、メソッドには2つの目的があります。 - プロパティを取得する - プロパティを設定する
- おっけー、これは分かる。
三角形型の操作も同じ原理です。「三角形さん、あんたを 3 , 4 , 5 という辺の長さで生成するよ」というコンストラクタもメソッドの一種で、1つのメッセージ渡し(message passing) です。
- うん、わかる、納得できる。
bless で classに神の祝福を
いろんなところで見てきて、いろんな本で見てきた bless が何をするものなのか、やっとわかった
ためしに、「続・はじめてのPerl」のOOPのところをさらっと読んでみると、わかる。
- ただただ本を写経していたけど、今は、その意味が(なんとなく)わかる。
- ここで、「続・はじめてのPerl」に行きたい気持ちを抑えて、本書を続行する。
- というか、自作のオブジェクト作ってみたいすぎて
ゲッター、セッター
- はい、これもイミフな単語でした。
- はじめて聞いたのは、たしか YAPC::Asia2013 でだった気がする
- よくそんなんで参加したなと思うが、参加したおかげで今があるので、積極的に参加するべき
- オブジェクトのプロパティ?「直接いじれば良いじゃん」とか思ってたので反省。
特に重要なのは、セッターで不法な値を代入したときに
croak
することです。
唐突に
すぐわかる オブジェクト指向 Perl 第10章 静的クラスの作成
9章はみるだけー
- 9章で参考にしている Calender というモジュールが CPAN からダウンロードできないみたいなので、見るだけ。
やってきましたオブジェクト指向
- 構造化プログラミングで再利用部分をサブルーチンにくくりだす:ok
- 再利用部分をファイルで分けて、モジュール化する:ok
- ファイルをまたいで、サブルーチンを呼び出す:ok
&package名::subroutin(@ARGV)
- 受け側には 引数(@ARGV) だけがわたる
- メソッド呼び出し:ok
- クラスの継承
- AUTOLOAD
- 継承されるのはメソッドだけ
- 変数は継承されない
use base qw(package)
、1モジュール1パッケージでスッキリ- あまり複雑な事はしないようにしよう・・・
- is a
- SUPER クラス
正直なところ
- 継承とオーバーライドについてはok
- でも、is a とかについては実際に使えるんかな、って気がする。
- 正直、メソッド呼び出しをしてパッケージ名がサブルーチンに渡されるメリットが分からない。
- 以上が今の到達地点
- とりあえずこのまま進めて、分からなかったらまた戻ってこよう。
すぐわかる オブジェクト指向 Perl 第8章 モジュールを使う use
モジュールのバージョン
@EXPORT
に$VERSION
変数を指定しておく事でモジュールがuse
した時のチェックを行う事が出来る、と- モジュール側で
package hogehoge; our @EXPORT = qw($VERSION); our $VERSION = "1.0";
としておいて、呼び出し側はこう
use hogehoge 2.0;
とするとエラーになる
おなじみ use
use strict
よく使うというか必須だよねしかし、そこで何をしているかは考えた事も無かった・・・
use モジュール名
;
という1つの文は、次の4行のプログラムと全く同じ動作になります。
BEGIN {
require モジュール名;
import モジュール名;
}なるほど
- つまり
use
はモジュールを読み込んで、さらにモジュール内の変数やサブルーチンをimport
すると- そのまんまやねん
うなる
変数は
my
をつけてレキシカル変数にする事で完全にプライバシーを守れ、モジュール外から見る事ができなくなりますが、サブルーチンだけは完全修飾名を使う事でモジュール外から見る事ができてしまいます。では、モジュール外からアクセスできないサブルーチンを定義する事はできるでしょうか?
our
をつけた変数やサブルーチンは当然外から参照ができる。my
をつけると外から参照ができない。- これはもしや、オブジェクト指向でいうカプセル化!?隠蔽化ってやつ!?
- うちのオブジェクト指向の主な知識は情報処理試験と「オブジェクト指向でなぜつくるのか 第2版 」です
- それはともかく、どうやって・・・
答えは、できます。ちょっと難しい話ですが、ここまでの知識で答えられるのでちょっと考えてみてください。
はいおわかりですか。無名サブルーチンリファレンスを使って、それをmy変数に代入すれば良いですね。
これをプライベートメソッドと言います。
- なるほど!
すぐわかる オブジェクト指向 Perl 第6章 、第7章
第6章 ライブラリを取り込むrequire
なるほど
- リストの要素である、数字の重複を排除する、というサブルーチン uniq
my @arr = ( 5, 4, 7, 4, 5, 7, 4, 3 ); sub uniq { my @in = @_; my %out = (); foreach my $in (@in) { $out{$in} = 1; } my @return = keys %out; } print uniq(@arr); #4375
- 配列をハッシュの key にして、その値に固定値で1を入力する。
- よくある
- でも、プログラムを学ぶ前だと分からなかったと思う。
- 準備された uniq 関数を使う事は出来ても、それを自分で実装できたかどうか・・・自信ない
「なんでもかまわない時は1」というのは Perl 仲間の間で、ゆるやかな合意として成立しているので、他の人がリストを読んだとき「ああ何でもかまわないから1を入れたんだな」とわかります
- この「1」ってのは、モジュール作ったときに最後に入れる「1」と同じなんかな?
- おいおい出てくるだろう
ライブラリ
次に arrUtil というライブラリを作っていきます。ここでライブラリ(library)とはサブルーチンを集めて色々なプログラムで呼び出せるようにするファイルの事です
- ライブラリの説明って以外と無かった気がする。
- もちろん、うちが覚えていないだけの可能性大
小ワザ
print join "\n" , @INC;
- ライブラリがおいてあるフォルダを表示するものなんだけど、なるほど、
join
をこうやって使うのか、と。- うちだったら、配列だから
foreach
つかって〜・・・ってなってたと思う。迂遠
- うちだったら、配列だから
- そして
@INC
の中に、.
があるから、カレントディレクトリ内のファイルもライブラリとして実行できるんね
第7章 名前空間を作るパッケージ
すぐわかる オブジェクト指向 Perl 第4章 、第5章
ハッシュスライス!
- 「第4章 ハッシュのリファレンス」については特に引っかかりなくすらすらと
- いや、一個だけあった、ひっかかったところ
$refMonth = { January => 1, February => 2, March => 3, April => 4, May => 5, June => 6, July => 7, August => 8, September => 9, October => 10, November => 11, December => 12, }; for( @{$refMonth}{ September, October, November } ) { print "autumn contains month No. $_\n"; }
@{$refMonth}{ September, October, November }
、普段ハッシュスライスを使わないので、初見で???だった- ハッシュスライスを使うべきところで、迂遠な書きかたしているなぁって思った
- 知っていれば回避できる苦労、知らないと回避できない苦労
- 学習大事よね
サブルーチンリファレンスがあるなら、サブルーチンは
- 「第5章 サブルーチンのリファレンス」
- サブルーチンもリファレンス化出来るなら、普通の(今まで学習してきた)サブルーチン構文とはいったい・・・って気持ちに
- サブルーチンのみならず、(普通の)配列も(普通の)ハッシュも、リファレンス化したものの前座なのだろうか・・・
シグナルハンドラ
ここでは Perl であらかじめ定義された特殊なハッシュ変数 %SIG というものを紹介します。この要素にサブルーチン リファレンスを入れると、プログラムが OS の機能によってあるシグナルを受け取ったときに、そのシグナルによってサブルーチンを実行します。
$SIG{'INT'} = sub {print "Oh, you pushed Ctrl-C! \n"}
- Ctrl + C を押したときに、 `SIG{'INT'} が呼び出されて、そのときハッシュの値に格納されたサブルーチンが動く、という理解で良いのかな?
この行では、ハッシュ要素
$SIG{'INT'}
に無名サブルーチンを代入しています。これによって、このプログラムがsigiht
をもらったときに実行する動作を定義しています
- 通常は Ctrl + C でプログラムの実行を止める
sigint
になるけど、その動きを上書きして制御できると。 - なるほど!
シュワルツ変換
- まず名前がかっこいい
- 大昔、シナリオシュミレーションゲームで「シュバルツシルト」ってゲームありましたなぁ
- たしか「続・はじめてのPerl」にも出てきた
- その時はふんふん、なるほどーで通り抜けた程度
- しかしこの本はみっちり解説がついている
- 詩を、各行の長さ順で並べ替えるという例題
- その1:各行の文字列の長さを配列に入れ、それを
sort
- その1:各行の文字列の長さを配列に入れ、それを
my @input = <DATA>; my @length = (); for (@input){ push @length , length($_) } print sort {$b <=> $a} @length;
- その2:各行そのものの文字列と、文字列の長さを配列に入れて、リファレンス化し、それを別な配列に入れる
for (@input) { my @lengthIndex = (); $lengthIndex[0] = $_; # 文字列そのものを配列の0番目に $lengthIndex[1] = length($_); # 文字列の長さを配列の1番目に push @length, \@lengthIndex; }
- その3:(その2で用意した)配列リファレンスを、文字列の長い順に並べ替えて、さらに別な配列に格納
- 一応これで例題は解ける
my @length2 = sort {$b->[1] <=> $a->[1]} @length; for (@length2){ say $_->[0]; }
その4:最初の
for
内で利用している配列を無名配列にする- なるほど、確かにこの
@lengthIndex
はfor
の中でしか使っていない、「使い捨て」の配列だ - これぞ無名配列!これこそanonymous Array !納得した!
- なるほど、確かにこの
その5:2回使われている
foreach
をmap
で置き換えていく
my @length = map { [ $_ , length($_) ] } @input; my @length2 = sort { $b->[1] <=> $a->[1] } @length; print map {$_->[0]} @length2;
- その6:
map
はUNIX
のパイプのように書けるので、中間配列が不要になる- ついでに不要なコードブロックも外す
print map $_->[0], sort { $b->[1] <=> $a->[1] } map [ $_, length($_) ], @input;
- 美しいなぁ・・・
すぐわかる オブジェクト指向 Perl 第3章 配列のリファレンス
わかる
- いきなり引用
ここで、2つの配列 @tanka と @kosuu を渡すと、売り上げ金額の合計を返すサブルーチン &uriage を考えてみます。
サブルーチンの中身を書く前に、メインのプログラムでこのサブルーチンを呼び出す方法を考えてみます。
&uriage(@tanka,@kosuu)
でしょうか。いや、ここでこれがいきなりダメです。
というのは、サブルーチンの引数は、サブルーチンの内部で
@_
という配列に入るのですが
- ガッテンガッテン!
- なるほど、そうか、そりゃそうだ
- サブルーチンの引数に配列そのまま突っ込むとダメ、展開されちゃうってのは知ってたけど、
@_
に入れるからか、そうか、改めて説明されるとそうか、そりゃそうだ
2つ以上の配列をサブルーチンに渡す
やる気とお時間があればここでいったんしおりを挟んで本を閉じ、ご自分で書いてみてください
- 学習本において、こう書かれていたら、やってみなくては実力が付かない
- 自分が最初に書いたもの
sub uriage { my ($ref_tanka , $ref_kosuu) = @_; my @tanka = @$ref_tanka; my @kosuu = @$ref_kosuu; my $sum; foreach my $soeji (0 .. $#tanka){ $sum += $tanka[$soeji] * $kosuu[$soeji]; } return $sum };
- 途中の
foreach my $soeji (0 .. $#tanka){
を
foreach my $soeji ($#tanka){
って書いて事故った。 - 同じ要素数の配列なので、配列のインデックス順に2つの配列にアクセスしていけば良いという考え
- 本に載ってたのはこちら
sub uriage { my ( $ref_tanka, $ref_kosuu ) = @_; my $uriage = 0; foreach my $tanka (@$ref_tanka) { my $kosuu = shift @$ref_kosuu; $uriage += $tanka * $kosuu; } return $uriage; }
shift
をそう使うのか!なるほどfor
ブロックの中で配列(のリファレンス)を操作するのかデリファレンスした配列をそのまま
foreach
に入れるのかいろんなやり方見るの楽しい。
- 短いプログラムですぐに理解できるようなものなら、なお楽しい
濃いなぁ
- 先の2章があっさりだったが本章は濃い
my @month = qw/january february march april may june july august september november deccember/; $refMonth = \@month; print "refMonth: $refMonth -> @$refMonth" , "\n" , "No.5 : $$refMonth[4]";
-
- 配列の要素はスカラーだから間違いではないか
$refMonth
のリファレントを配列としてでリファレンスしたものに、[4]
をインデックス付けしたもの Perlエンジンの名前の解釈の仕方
- Perl の気持ち
$$refMonth[4]
と ${$refMonth[4]}
の違い
$$refMonth[4]
はリファレンス化した配列の4番目のインデックスの要素${$refMonth[4]}
は・・・
my $rm1 = 'january'; my $rm2 = 'february'; my $rm3 = 'march'; my $rm4 = 'april'; my $rm5 = 'may'; my $rm6 = 'june'; my $rm7 = 'july'; my $rm8 = 'august'; my $rm9 = 'september'; my $rm10 = 'october'; my $rm11 = 'november'; my $rm12 = 'december'; my @refMonth = ( \$rm1, \$rm2, \$rm3, \$rm4, \$rm5, \$rm6, \$rm7, \$rm8, \$rm9, \$rm10, \$rm11, \$rm12 ); print ${$refMonth[4]}; # may
- 配列
@refMonth
の5番目に入っているスカラーのリファレンス- わかるかぁっ!
- 書いてみると分かる
- わかるかぁっ!
- 苦しい、こうやって解釈していくの苦しい。慣れるもんなんだろうか。
すばらしい「ぶつぶつコンンピュータ」
- この章、配列のリファレンスを1行ごとに解説する「ぶつぶつコンンピュータ」、つまりPerlを実行するコンピュータの気持ちになってリファレンスを紐解いていく下りがあるんだけど、これが良い
- くどいけど良い
- うちのような初学者には、これが本当に理解の助けになる。
- 例えば、
$month->[2][0]
ってリファレンスについて
month
という名前があるなー- 前に
$
があるからスカラーだなー- 後ろに
->
があるから$month
はリファレンスだなー$month->[2]
ということはリファレントは配列で、その第3要素を返せばいいなー(配列インデックスはゼロ始まりだからなー)- さらに
[0]
があるから、$month
は別の配列へのリファレンスで、そのリファレントの第1要素を返せばいいなー
- これを追体験していく事で、ほんと理解が深まるんだよなぁ。
- 全編これだと本のサイズがふくれあがっていくらページあっても足りないし、くどいけど
無名感、即時感
- 無名配列、書いてはいるので、何となく分かる
- 分かるけど、どう、「無名」なのかがずっと引っかかっている
- アクセスするときは配列名がないため、リファレンス通しており、リファレンス名は配列名ではない・・・ってのは分かる・・・よ
無名配列、文字から感じるものと実際のものがイマイチ結びつかないんよね。今は分かるんだけど。・・・そうだ!原典の英語ではなんて言ってるんだろ?そっちが分かりやすいかも!と思ったら、anonymous array 。うーん。うーん・・・
— sironekotoro (@sironekotoro) 2016年4月3日
anonymous っていうと、今時だとあのガイ・フォークスの仮面思い出しちゃう
そこに(勝手にうちがメンターとして仰ぎ見てる)@xtetsujiさんが助け舟を
@sironekotoro 本当に変数名を付けず、使って即時捨てると無名感が出ると思います。my $mon = +{Jan=>1,Feb=>2,…}->{$monname}; といったハッシュリファレンスもとい無名ハッシュとかはどうでしょう。
— OGATA Tetsuji (@xtetsuji) 2016年4月3日
- 無名感!即時感!こっちの方がしっくりくる。なるほど。
- Javascript で「無名関数」を「即時関数」って言ってる本があったなそういえば
- いちいち配列名をつけず、そのまま配列作ってしまう即時・即席感