« Perl でオブジェクト指向 C++風 その2 クラス変数 | トップページ | Haskell の callCC で goto を作る »

2011年1月 7日 (金)

Perl でオブジェクト指向 C++風 その3 ローカル関数

先の記事で「パッケージ」でインポートした関数などを、「クラス」で使う方法を書いたが、インポートした関数の他に、Main パッケージで定義した「ローカル関数」も「クラス」で使いたくなるのが当然である。(というより、それができないことにさっき気付いた。)本稿ではほぼソースだけだがその方法を示す。
先の記事と発想はほぼ同じだが、「型グロブ」という機能を使って実現できる。

#!/usr/bin/perl

use strict;
use warnings;
use utf8; # Japanese

BEGIN {
  my @mypackage = qw(
                    Main
                    Main::_Simple
                    Main::_B
                 );

  foreach my $p (@mypackage) {
    eval <<"EOM";
    {
      package $p;
      use Math::Trig; # for pi
      use Storable qw(dclone);
    }
EOM
    die $@ if $@;
  }

  my @myfunction = qw(
                       Main::local_function_1
                    );
  {
    no strict; ## 型グロブの警告を停止。

    foreach my $p (@mypackage) {
      for my $f (@myfunction) {
        my @f = split("::", $f);
        *{$p . "::" . $f[$#f]} = \&{$f};
      }
    }
  }
}

package Main;

{
  package Main::_Simple;
  ## Main::_Simple の定義はこれまでどおり。

  my %template = ("Main::_Simple" => {});

  sub extend_template {
    my $class = shift;
    my @hash = @_;
    if (exists $template{$class}) {
      $template{$class} = {%{$template{$class}}, @hash} if @hash;
    } else {
      $template{$class} = 
        {(map {
                $_->extend_template() if ! exists $template{$_};
                %{$template{$_}};
              } (eval '@{' . $class . '::ISA}')),
         @hash
        };
    }
    return $template{$class};
  }

  sub get_template {
    my $class = shift;
    return $class->extend_template();
  }

  sub new {
    my $class = shift;
    my $obj = dclone($class->get_template());
    bless $obj, $class;
    return $obj;
  }
}


{
  package Main::_B;
  use base qw(Main::_Simple);

  __PACKAGE__->extend_template
    (
     data => 1.0, # ここに data の説明を書こう!
    );

  sub method_1 {
    my $self = shift;
    my ($arg1) = @_;
    $self->{data} = $self->{data} + pi / $arg1;

    ## ここで「ローカル関数」を使う。
    local_function_1();

    return $self->{data};
  }
}


## ただ print するだけの「ローカル関数」。
sub local_function_1 {
  print "OK\n";
}

MAIN:
{
  ## Main::_B::method_1 から local_function がちゃんと呼ばれる。

  my $b = Main::_B->new();

  print $b->method_1(7.0) . "\n";
}


つまり、「プロトタイプ宣言」のようなものが必要でいいという発想である。ソースの「頭」が重い感じがするが、慣れの問題だろうと思いたい。

「ローカル関数」のモジュール名を Main と想定してあるので、変更する際はそのあたりに注意する必要がある。


関連

example_oo_pl.shar。上のソースの元ととなった example_oo_fun.pl やその他の例をまとめたアーカイブ。(シェルアーカイブ形式。シェルコマンドとして実行するかunshar を使う。)

Perl でオブジェクト指向 C++風》。「先の記事」。冗長になるのでまとめなかったが、先の記事が便利な方は必ず本稿のところでつまずくにちがいない。

Perl でオブジェクト指向 C++風 その2 クラス変数》。クラス変数を使ってみる例。
更新: 2011-01-07
初公開: 2011年01月07日 22:40:11
最新版: 2011年01月14日 18:42:25

2011-01-07 22:40:08 (JST) in Perl | | コメント (1) | トラックバック (0)

Perl」カテゴリ内の最近の記事

批評や挨拶のためのネットコミュニティ

  • はてなブックマーク(って何?) このエントリーをはてなブックマークに追加 このエントリーを含むはてなブックマーク このエントリーを含むはてなブックマーク
  • Twitter (って何?)

トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/93568/50520896

トラックバックのポリシー

他サイトなどからこの記事に自薦された関連記事(トラックバック)はまだありません。
» JRF のソフトウェア Tips:Perl でオブジェクト指向 C++風 その3 ローカル関数 (この記事)

コメント

banana 更新:@myfunction の関数名にパッケージ名を足すようにした。一つのパッケージ内に利便性のため別のパッケージにできるものも書いておくとき必要で、@mypackage と表現も揃うのでこうした。それにつれ、shar が変わっている。今回のものは example_oo_pl-20110114.shar

投稿: JRF | 2011-01-14 18:48:10 (JST)

コメントを書く



(メールアドレス形式)


※匿名投稿を許可しています。ゆるめのコメント管理のポリシーを持っています。この記事にまったく関係のないコメントはこのリンク先で受け付けています。
※暗号化パスワードを設定すれば、後に「削除」、すなわち JavaScript で非表示に設定できます。暗号解読者を気にしないならメールアドレスでもかまいません。この設定は平文のメールで管理者に届きます。
※コメントを書くために<b>ボールド</b>、<pre>詩文やソースコード</pre>、<a href="">リンク</a>、その他のHTMLタグが使えます。また、漢字[かんじ]でルビが、[google: キーワード] で検索指定が使えます。


ランダムことわざ: 鶴は千年、亀は萬年。