--- title: Perlのオブジェクト指向 author: kazu634 date: 2008-10-11 wordtwit_post_info: - 'O:8:"stdClass":13:{s:6:"manual";b:0;s:11:"tweet_times";i:1;s:5:"delay";i:0;s:7:"enabled";i:1;s:10:"separation";s:2:"60";s:7:"version";s:3:"3.7";s:14:"tweet_template";b:0;s:6:"status";i:2;s:6:"result";a:0:{}s:13:"tweet_counter";i:2;s:13:"tweet_log_ids";a:1:{i:0;i:4333;}s:9:"hash_tags";a:0:{}s:8:"accounts";a:1:{i:0;s:7:"kazu634";}}' categories: - Perl --- <div class="section"> <p> Perlでオブジェクト指向をする方法を学ぶ。テキストは『<a href="http://d.hatena.ne.jp/asin/4774135046" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://d.hatena.ne.jp/asin/4774135046', 'すぐわかる オブジェクト指向 Perl');">すぐわかる オブジェクト指向 Perl</a>』。<a href="http://blog.livedoor.jp/dankogai/" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://blog.livedoor.jp/dankogai/', 'Perlの偉い人');" target="_blank">Perlの偉い人</a>もお勧めしていた本だよ。 </p> <h4> 対象とする読者(というかこれ自分用の備忘録) </h4> <p> Javaとかで簡単なオブジェクト指向を学んでいる人であれば、今回の自分用メモを読むとPerlでクラスを作成するポイントがわかる…と思います。はい。 </p> <h4> 静的なクラスを作る </h4> <p> 静的なクラスというのはコンストラクタなんかでインスタンス化しなくても使えるクラス…というような雰囲気を感じる。違うかもしれないけれど。。。 </p> <p> とりあえず三角形の面積を求めるクラスを作るのだけれど、 </p> <ul> <li> Figureクラス <ul> <li> Triangleクラス <ul> <li> Regular Triangleクラス </li> </ul> </li> </ul> </li> </ul> <p> というような継承関係をしているとして、以下のソースをご覧ください: </p> <p> <a name="seemore"></a> </p> <h4> Figureクラス </h4> <pre class="syntax-highlight"> <span class="synStatement">use strict</span>; <span class="synStatement">use warnings</span>; <span class="synComment"># Must specify the package name!</span> <span class="synStatement">package</span><span class="synType"> Figure;</span> <span class="synStatement">sub</span><span class="synIdentifier"> AUTOLOAD </span>{ <span class="synStatement">my</span> (<span class="synIdentifier">$class</span>, <span class="synIdentifier">@rest</span>) = <span class="synIdentifier">@_</span>; <span class="synStatement">our</span> <span class="synIdentifier">$AUTOLOAD</span>; <span class="synStatement">warn</span> <span class="synConstant">"You are about to invoke </span><span class="synIdentifier">$AUTOLOAD</span><span class="synConstant"> using the argument "</span>, <span class="synStatement">join</span>(<span class="synConstant">', '</span>, <span class="synIdentifier">@rest</span>), <span class="synConstant">".</span><span class="synSpecial">\n</span><span class="synConstant">"</span>; <span class="synStatement">warn</span> <span class="synConstant">"But I don't know how to do it!</span><span class="synSpecial">\n</span><span class="synConstant">"</span>; <span class="synStatement">return</span> <span class="synConstant">"UNKNOWN"</span>; } <span class="synConstant">1</span>; </pre> <p> スーパークラスとして存在するクラス。packageで名前空間としてFigureを指定している。AUTOLOADは存在しないメソッド呼び出しがあったときに、それを引き受けるための専用のメソッド。 </p> <h4> Triangleクラス </h4> <pre class="syntax-highlight"> <span class="synStatement">use strict</span>; <span class="synStatement">use warnings</span>; <span class="synComment"># Must specify the package name!</span> <span class="synStatement">package</span><span class="synType"> Triangle;</span> <span class="synStatement">use base</span> <span class="synConstant">'Figure'</span>; <span class="synComment"># Must include these 3 lines below. It's a convention!</span> <span class="synStatement">sub</span><span class="synIdentifier"> space </span>{ <span class="synStatement">my</span> (<span class="synIdentifier">$class</span>, <span class="synIdentifier">$a</span>, <span class="synIdentifier">$b</span>, <span class="synIdentifier">$c</span>) = <span class="synIdentifier">@_</span>; <span class="synStatement">my</span> <span class="synIdentifier">$s</span> = (<span class="synIdentifier">$a</span> + <span class="synIdentifier">$b</span> + <span class="synIdentifier">$c</span>) / <span class="synConstant">2</span>; <span class="synStatement">my</span> <span class="synIdentifier">$space</span> = <span class="synStatement">sqrt</span>(<span class="synIdentifier">$s</span> * (<span class="synIdentifier">$s</span> - <span class="synIdentifier">$a</span>) * (<span class="synIdentifier">$s</span> - <span class="synIdentifier">$b</span>) * (<span class="synIdentifier">$s</span> - <span class="synIdentifier">$c</span>)); <span class="synStatement">return</span> <span class="synIdentifier">$space</span>; } <span class="synConstant">1</span>; </pre> <p> 継承をするときは </p> <pre class="syntax-highlight"> <span class="synStatement">use base</span> <span class="synConstant">'module name'</span>; </pre> <p> もしくは </p> <pre class="syntax-highlight"> <span class="synStatement">use base</span> <span class="synConstant">qw(module name)</span>; </pre> <p> とする。 </p> <h4> RegularTriangleクラス </h4> <pre class="syntax-highlight"> <span class="synStatement">use strict</span>; <span class="synStatement">use warnings</span>; <span class="synComment"># Must specify the package name!</span> <span class="synStatement">package</span><span class="synType"> RegularTriangle;</span> <span class="synStatement">use base</span> <span class="synConstant">'Triangle'</span>; <span class="synStatement">sub</span><span class="synIdentifier"> space </span>{ <span class="synStatement">my</span> (<span class="synIdentifier">$class</span>, <span class="synIdentifier">$a</span>) = <span class="synIdentifier">@_</span>; <span class="synIdentifier">$class</span>->SUPER::space(<span class="synIdentifier">$a</span>, <span class="synIdentifier">$a</span>, <span class="synIdentifier">$a</span>); } <span class="synConstant">1</span>; </pre> <p> 継承している一つ上のクラスを指すには「SUPER」を用いる。 </p> <h4> テスト用スクリプト </h4> <pre class="syntax-highlight"> <span class="synComment"># === Libraries ===</span> <span class="synStatement">use strict</span>; <span class="synStatement">use warnings</span>; <span class="synStatement">use </span>Triangle; <span class="synStatement">use </span>RegularTriangle; <span class="synComment"># === Main part ===</span> <span class="synStatement">my</span> <span class="synIdentifier">$a</span> = <span class="synConstant">3</span>; <span class="synStatement">my</span> <span class="synIdentifier">$b</span> = <span class="synConstant">4</span>; <span class="synStatement">my</span> <span class="synIdentifier">$c</span> = <span class="synConstant">5</span>; <span class="synStatement">my</span> <span class="synIdentifier">$space</span> = Triangle->space(<span class="synIdentifier">$a</span>, <span class="synIdentifier">$b</span>, <span class="synIdentifier">$c</span>); <span class="synStatement">print</span>(<span class="synConstant">"Triangle: </span><span class="synIdentifier">$space</span><span class="synSpecial">\n</span><span class="synConstant">"</span>); <span class="synIdentifier">$a</span> = <span class="synConstant">6</span>; <span class="synIdentifier">$space</span> = RegularTriangle->space(<span class="synIdentifier">$a</span>); <span class="synStatement">print</span>(<span class="synConstant">"Regular_Triangle: </span><span class="synIdentifier">$space</span><span class="synSpecial">\n</span><span class="synConstant">"</span>); <span class="synIdentifier">$space</span> = Triangle->aaa(<span class="synIdentifier">$a</span>); </pre> <p> クラスのメソッド呼び出しには「クラス名->メソッド名」を用いる。 </p> <h4> .pmファイルを作るときのテンプレート(暫定) </h4> <pre class="syntax-highlight"> <span class="synStatement">use strict</span>; <span class="synStatement">use warnings</span>; <span class="synComment"># Must specify the package name!</span> <span class="synStatement">package</span><span class="synType"> xxx;</span> <span class="synComment"># Inheritance from ...</span> <span class="synComment"># use base qw(module name);</span> <span class="synComment"># If you use the module(s), you must put here:</span> <span class="synStatement">use </span>Carp <span class="synConstant">qw(croak)</span>; <span class="synComment"># extended debug module</span> <span class="synComment"># === Constructor ======================================</span> <span class="synComment"># You can name the constructor any names you want.</span> <span class="synComment"># But, it's a convention to name the constructor new.</span> <span class="synComment"># ======================================================</span> <span class="synComment"># sub new {</span> <span class="synComment"># my ($class, $a, $b, $c) = @_;</span> <span class="synComment"># my $self = {</span> <span class="synComment"># a => $a,</span> <span class="synComment"># b => $b,</span> <span class="synComment"># c => $c,</span> <span class="synComment"># };</span> <span class="synComment"># bless $self, $class;</span> <span class="synComment"># return $self;</span> <span class="synComment"># }</span> <span class="synComment"># === Deconstructor ===</span> <span class="synComment"># sub DESTROY {</span> <span class="synComment"># }</span> <span class="synComment"># ===============================================================</span> <span class="synComment"># If you write a super class,</span> <span class="synComment"># it is recommended that you should write an AUTOLOAD method.</span> <span class="synComment"># ===============================================================</span> <span class="synComment"># sub AUTOLOAD {</span> <span class="synComment"># }</span> <span class="synConstant">1</span>; </pre> <h4> 疑問点 </h4> <ul> <li> privateがないけど、外部からアクセスできないメソッドを作りたいときはどうするの? <ul> <li> 無名サブルーチンを使うよ!…でも、なんか美しくない気がする。。。 </li> </ul> </li> </ul> <div class="hatena-asin-detail"> <a href="http://www.amazon.co.jp/dp/4774135046/?tag=hatena_st1-22&ascsubtag=d-7ibv" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://www.amazon.co.jp/dp/4774135046/?tag=hatena_st1-22&ascsubtag=d-7ibv', '');"><img src="https://images-na.ssl-images-amazon.com/images/I/410B5%2BzbIxL._SL160_.jpg" class="hatena-asin-detail-image" alt="すぐわかる オブジェクト指向 Perl" title="すぐわかる オブジェクト指向 Perl" /></a></p> <div class="hatena-asin-detail-info"> <p class="hatena-asin-detail-title"> <a href="http://www.amazon.co.jp/dp/4774135046/?tag=hatena_st1-22&ascsubtag=d-7ibv" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://www.amazon.co.jp/dp/4774135046/?tag=hatena_st1-22&ascsubtag=d-7ibv', 'すぐわかる オブジェクト指向 Perl');">すぐわかる オブジェクト指向 Perl</a> </p> <ul> <li> <span class="hatena-asin-detail-label">作者:</span> <a href="http://d.hatena.ne.jp/keyword/%BF%BC%C2%F4%C0%E9%BF%D2" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://d.hatena.ne.jp/keyword/%BF%BC%C2%F4%C0%E9%BF%D2', '深沢千尋');" class="keyword">深沢千尋</a> </li> <li> <span class="hatena-asin-detail-label">出版社/メーカー:</span> <a href="http://d.hatena.ne.jp/keyword/%B5%BB%BD%D1%C9%BE%CF%C0%BC%D2" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://d.hatena.ne.jp/keyword/%B5%BB%BD%D1%C9%BE%CF%C0%BC%D2', '技術評論社');" class="keyword">技術評論社</a> </li> <li> <span class="hatena-asin-detail-label">発売日:</span> 2008/06/20 </li> <li> <span class="hatena-asin-detail-label">メディア:</span> 大型本 </li> <li> <span class="hatena-asin-detail-label">購入</span>: 12人 <span class="hatena-asin-detail-label">クリック</span>: 195回 </li> <li> <a href="http://d.hatena.ne.jp/asin/4774135046" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://d.hatena.ne.jp/asin/4774135046', 'この商品を含むブログ (35件) を見る');" target="_blank">この商品を含むブログ (35件) を見る</a> </li> </ul> </div> <div class="hatena-asin-detail-foot"> </div> </div> </div>