• ベストアンサー

リファレンスの機能

リファレンスではサブルーチンとして呼び出すライブラリ自体を変数に格納することができるのでしょうか?その概念がよくわかりません。たとえば HOGE.plというプログラムがあり、 (1)use INILOAD; (2)$HOGE::INI = new INILOAD inifile=>'CONFIG.ini'; (3)($ret, $MESS, $s) = $HOGE::INI->load; このloadがどこのことなのか、を調べているうちにINILOAD.pmのなかにあることがわかったのです。 そこで(3)をとおった時点で$HOGE::INIの中身をlogで確認したら INILOAD=HASH(0x1857b04) が格納されていました。これってINILOAD.pmそのものを格納しているということでしょうか?だとすると上記文でなぜ$HOGE::INIのなかに ライブラリ名が格納されるのですか? 最後にINILOAD.pmのnewを記載します。 sub new { my($class) = shift; my($args) = {@_}; &init(); bless { INIFILE => $args->{inifile} || 'default.ini', }, $class; } sub init { my($self) = shift; $self->{STATUS} = 0; $self->{STATUS_MESS} = 'undefined'; undef $self->{DATA}; } おそらくbless以下の部分がキーになるのかとは思いますが、私の理解は 『ハッシュの引数の値をkey:inifile,値'default.ini'としてこのプログラム上で読めるようにし、それに$classを付加したものをINIFILE というグローバルな変数に代入する』 なのですが、どうもしっくりきません。ご指摘よろしくお願いいたします。

  • Perl
  • 回答数3
  • ありがとう数2

質問者が選んだベストアンサー

  • ベストアンサー
noname#9431
noname#9431
回答No.1

これはクラスを記述するPerl独得のやり方です。 こまかい説明は man perlboot でお調べ下さい。 Googleで調べると日本語訳も見つかると思います。

cshoaucmoa
質問者

お礼

ありがとうございます。 日本語訳見つかりました。まだ完全に読めていませんが、勉強させていただきます。

その他の回答 (2)

  • hikomin
  • ベストアンサー率63% (40/63)
回答No.3

補足です。 既にあるとおり、これはオブジェクト指向で書かれているわけですが、問題はコンストラクタ(ここではnewメソッド)の最後のblessです。blessはオブジェクト生成に使う関数で、クラスの名前を結びつけたリファレンスを作成します。INILOAD=HASH(0x1857b04) となっているのは、INILOADと結びつけられたHASHである事を表しています。これによって、オブジェクトが迷わず自分の名前(クラス名)を知る事が出来るわけです。 例えば$HOGE::INI->load;と言う風にloadメソッドを呼んでも、$HOGE::INIが何に属しているかを知らなければ(他のクラスでもloadメソッドを定義しているかもしれないわけで)どのloadメソッドなのか分かりませんが、Perlでは上記のやり方で、属しているクラスを示しているわけです。

cshoaucmoa
質問者

補足

回答ありがとうございます。 bless自体、まだあまり理解できていないのですが、要は 『”$HOGE::INI = new INILOAD inifile=>'CONFIG.ini';”で与えた引数 inifile=>'CONFIG.ini'というものをINILOAD.pm上で{inifile} || 'default.ini'(inifileもしくはdefaule.ini)として紐付け、INILOAD.pmで使用できるようにする』といった感じでしょうか?

回答No.2

これは、たぶんクラスの指定かと思われます。 use INILOAD; これは、INILOADというクラスを使用するという宣言。 $HOGE::INI = new INILOAD inifile=>'CONFIG.ini'; $HOGEという名前空間の中のINIという変数にINILOADのクラスを引数鍵がinifile、値がCONFIG.iniというハッシュを引数として作成。 ($ret, $MESS, $s) = $HOGE::INI->load; $HOGE::INIに格納されたクラスのうちloadを実行。 その戻り値として$ret,$MESS,$sを返す。 たぶん、これで間違いないはずです。 .pmは、パールモジュールなので、クラス指向言語のはずですので、

cshoaucmoa
質問者

お礼

どうもありがとうございました。 なかなか考え方自体を改革するのは難しいのですが、少しずつPERLに慣れていきたいと思います。

関連するQ&A

  • perlのクラスについて

    perlでクラスを作成しています。その際、コンストラクタnewで無名配列を定義して、funcメソッドで、この無名配列に値をいれるにはどうすればよいでしょうか? sub new { my $class = shift; my $self->array = []; bless($self, $class); return $self; } sub func { my $self = shift; $self->arrayに配列のデータを入れる。 }

    • ベストアンサー
    • Perl
  • オブジェクト指向プログラミング

    Perlのクラス定義の例題なんですが、わからないところがあります。 ファイルCapFile.pm package CapFile; sub new{ my $class = shift; my $path = shift; return(bless { ':path' => $path }, $class); } sub read { my $obj = shift; my $path = $obj->{':path'}; ..... ファイルcap-test #!/usr/bin/perl use CapFile; $cap = new CapFile ('/etc/termcap'); $cap->read(); ... サブルーチンreadにある my $path = $obj->{':path'}; なんですが、呼び出し側では引数がないのですが、$objには何が入っているんでしょうか。 そして$pathには何が入るんでしょうか。

    • ベストアンサー
    • Perl
  • use baseしたpackageのローカル変数の書き換え

    packageを継承した場合、 継承先(以下のMyPkg)で継承もと(MyBase)のローカル変数($localValue)を直接書き換える方法はありませんか? package MyBase; my $localValue; sub doBase{ my $self=shift; $localValue ={ 'hanako'=>{'id'=>1, 'pref'=>'tokyo'} }; } sub getPref { my $self=shift; my $name=shift; $localValue->{$name}{'pref'}; } package MyPkg; use base qw(MyBase); sub new{ my $class=shift; my $self={}; bless $self, $class; return $self; } sub doAnything { # この中でMyBaseの$localValueを直接書き換えたい $localValue ={ 'taro'=>{'id'=>2, 'pref'=>'osaka'} }; } ------main:: my $pkg=new MyPkg; $pkg->doSomething; print $pkg->getPref('hanako'); $pkg->doAnything; print $pkg->getPref('taro'); ---------- 以下のような感じでmyBaseの中に$localValueを返すサブルーチンを作っておけば、 print $pkg->localValue->{'hanako'}{'pref'}; などと取得は出来ますが、 $pkg->localValue->{'hanako'}{'pref'}='kyoto'; のような代入は無理みたいでした。 package MyBase; my $localValue; sub localValue{ my $self=shift; $localValue; } doBaseのようなサブルーチン経由で書き換えていますが、 use baseしていても、やはりそうしないとダメでしょうか。 Windows、ActivePerl、perl 5.10.0 Linux、Perl5.8

  • Perl、オブジェクト指向での初期設定ファイルについて。

    Perl、オブジェクト指向での初期設定ファイルについて。 最近、Perlでのオブジェクト指向を勉強中です。 今までのプログラムをオブジェクト指向に書き直そうと思っています。 クラスを作成して呼び出す程度までは理解できたのですが、 今まで、サーバの絶対パスや、データベースの名称などを、 config.pl というファイルを作って、グローバル変数で宣言していました。 例 $local_parh = "/virtual/xxx/bbb/public_html"; $dbname = "testdb"; $dbuser = "username"; でも、オブジェクト指向では、グローバル変数を使わないようにするということで、 このあたりをふつうはどんなふうに作成するのかとおもったのですが、 なかなか検索しても見つかりません。(検索の仕方が悪いのかもしれませんが) 今思いつく方法は、config.pm などを作って -------------------------------------------------- package Config; sub new{ my $class = shift; my $self= { local_path => '/virtual/aaa/bbb/public_html', dbname => 'testdb', dbuser => 'username' }; return bless ($self,$class); } sub get_local_path { my ($self, $name) = @_; return $self->{'local_path'}; } -------------------------------------------------- use Config; $obj=new Config(); $local_path = $obj->get_local_path(); -------------------------------------------------- とするような感じなのですが、なんだかスマートじゃない気がするので 普通ははどんなふうに書くのか教えてもらえますか?

    • ベストアンサー
    • Perl
  • method#invoke のラッパ

    下記のようなリフレクション(動的なメソッド呼び出し)の汎用的なラッパ関数を作成しています。 class Wrapper { public static void main(String[] args) { Hoge hoge = new Hoge(); // (1) Wrapper.call(hoge, "testMethod", new Human()); // (2) これはNoSuchMethodException例外発生 Wrapper.call(hoge, "testMethod", new Japanese()); // (3) これもNoSuchMethodException Wrapper.call(hoge, "testMethod", (Human) new Japanese()); } public static Object call(Object obj, String method_name, Object ...args) { try { // 引数のクラス配列を取得 Class[] class_ary = new Class[args.length]; for (int i=0; i<args.length; i++) class_ary[i] = args[i].getClass(); Class c = obj.getClass(); // メソッドインスタンスを取得 Method method = c.getMethod(method_name, class_ary); // 実行 return method.invoke(obj, args); }catch (Exception e) { e.printStackTrace(); return null; } } } class Hoge { public void testMethod(Human h) { System.out.println(h.getClass()); } } class Human { } class Japanese extends Human { } 一見うまくうごくようにみえたのですが (2)のようにすると例外が発生することが最近わかりました。 親クラスにキャストした(3)でも同様です。 理由は // 引数のクラス配列を取得 Class[] class_ary = new Class[args.length];  for (int i=0; i<args.length; i++)   class_ary[i] = args[i].getClass(); のgetClass()の部分がキャストしようがしまいが Japaneseのクラスインスタンスを返すからだというのはわかっているのですが、他の方法が思いつきません。 多態性を備えたラッパ関数を作成することは無理でしょうか? 何か解決策があればアドバイスをお願いします。

    • ベストアンサー
    • Java
  • モジュールのコンストラクタとスコープ

    perlのモジュールを使用する際のコンストラクタで {  package TEST;  new {   my $pkg = shift ;   my @arr1 = (1,2,3,4,5,6) ;   my $self = {    member => "hoge",    arr => \@arr1   }   bless $self,$pkg;  }  sub dref {   $self = shift ;   print @{$self->{arr}};  } } 上記のようにコンストラクタ内でmy指定した@arr1のリファレンスをインスタンスに与えた場合、同package内でデリファレンスできました。($obj->drefを実行した場合配列の中身が表示された) この場合、スコープはどのようになっているのでしょうか。 ( 1.値が保証される 2.参照できるが値を保証しない 3.表示できたのは偶然で、本当は致命的なエラー )

    • ベストアンサー
    • Perl
  • クラスインスタンスとクラス型変数の配列

    C++からシフトしてきた若輩JAVAプログラマですが、微妙に理解しきれない部分があるため、お知恵をお借りしにきました。 最初にC++のサンプルを書かせていただきます。 ----- C++ ----- class Hoge {  /* 実装省略 */ } int main( void ) {  Hoge *hoge = new Hoge ;  Hoge *hoge = new Hoge[10] ; } --------------- これをJAVAで実装した場合、以下のようになると思います。 ----- JAVA ----- class Hoge {  /* 実装省略 */ } class Test {  public static void main( String[] args )  {   Hoge hoge = new Hoge() ; /* 1 */   Hoge[] hoge = new Hoge[10] ; /* 2 */  } } --------------- JAVAの場合、2ではクラスのインスタンスが確保されていないことを知りました。C++ではnewの役割が「何かをメモリ上に確保する(malloc)」という意味合いであったのに対し、JAVAの場合は考え方が違うものだということでしょうか。 そうすると、 int[] a = new int[10] ; と、 Hoge[] hoge = new Hoge[10] ; のnewは、意味が違うという認識にたどり着いてしまうのですが、そうなると『妙な』気持ちがしてしまいます。そんな面倒な言語仕様では無い気もしますし。 私の考え方が間違っている可能性が高いと思いますので、教唆していただけると助かります。 よろしくお願いします。

    • ベストアンサー
    • Java
  • perl の複雑(?)なクラス定義(データ構造)

    以下のようなクラスを作成したいのですが、どのようにクラスとして定義して、どのように呼び出せばよいのでしょうか。特に「score」の部分の記述方法が良く分かりません。 オブジェクト指向(とくにPerl)はあまり経験がない初心者です。 -------------------- データ構造 name addr score--+-- math +-- english +-- science -------------------- クラス記述 package myClass; $ref_score->{math} = '30'; # <-- 正しい? $ref_score->{english} = '40'; # <-- 正しい? # ... sub new { my $class = shift; my $self={}; $self->{name} = 'tanaka'; $self->{addr} = 'tokyo'; $self->{score} = $ref_score; # <-- 正しい? bless $self, $class; } -------------------- メイン文 package main; $inst[0] = myClass::new(); $inst[0]->{name} = "OVERWRITE_NAME"; $inst[0]->{score}->{math} = "OVERWRITE_SCORE_MATH"; print $inst[0]->{module}."\n"; # 出る print $inst[0]->{score}->{math}."\n"; # オーバーライトした値は出るが... print $inst[0]->{score}->{english}."\n"; # 初期値のままの値は表示してくれない... 宜しくお願いいたします。

  • sendmail -fオプションの指定はどこで行えばいいでしょうか?

    キャノネットというサーバーでフリーのメールフォームCGI設置を試みました、-fと-tオプション設定を行わなければならないみたいなのですが、今回使用したいCGIの初期設定ファイルsendmail指定部分下記に #sendmailのパス $init->{sendmail_path} = '/usr/local/bin/sendmail -t -f ' メールアドレス' '; と指定しましたがCGIエラーとなってしまい、どうやらプログラム内を書き換える必要があるみたいなのですが、知識不足のため どうやって変更するのかがわからず困っております。 お詳しい方、下記のプログラム内の変更部分をお教え下さい。 よろしくお願い致します。 (CGIはURLのものを使用しております。) http://www.web-liberty.net/download/mailplus/index.html -------------------------------------------------- package webliberty::Sendmail; use strict; use Jcode; use webliberty::Encoder; ### コンストラクタ sub new { my $class = shift; my $self = { sendmail => shift, send_to => undef, send_from => undef, subject => undef, name => undef, message => undef, files => undef, x_mailer => undef }; bless $self, $class; return $self; } ### メール送信 sub sendmail { my $self = shift; my %args = @_; $self->{send_to} = $args{'send_to'}; $self->{send_from} = $args{'send_from'}; $self->{subject} = $args{'subject'}; $self->{name} = $args{'name'}; $self->{message} = $args{'message'}; $self->{files} = $args{'files'}; $self->{x_mailer} = $args{'x_mailer'}; if (!$self->{send_to}) { $self->{send_to} = 'example@example.com'; } if (!$self->{send_from}) { $self->{send_from} = 'example@example.com'; } if (!$self->{subject}) { $self->{subject} = 'No Subject'; } if (!$self->{message}) { $self->{message} = 'No Message'; } if (!$self->{x_mailer}) { $self->{x_mailer} = 'Web Liberty'; } foreach ($self->{subject}, $self->{name}, $self->{message}) { $_ =~ s/<br ?/>/?n/g; $_ =~ s/&amp;/&/g; $_ =~ s/&lt;/</g; $_ =~ s/&gt;/>/g; $_ =~ s/&quot;/"/g; } if ($self->{name}) { $self->{send_from} = "?"" . $self->_encode($self->{name}) . "?" <$self->{send_from}>"; } $self->{message} =~ s/?xEF?xBD?x9E/?xE3?x80?x9C/g; $self->{message} = Jcode->new($self->{message}, 'utf8')->jis; my @files = split(/?n/, $args{'files'}); my $boundary; if ($files[0]) { require webliberty::File; $boundary = time; while ($self->{message} =~ /$boundary/) { $boundary++; } } open(webliberty_Sendmail, "| $self->{sendmail} -t") or return(0, "Sendmail Error : $self->{sendmail}"); print webliberty_Sendmail "X-Mailer: $self->{x_mailer}?n"; print webliberty_Sendmail "To: $self->{send_to}?n"; print webliberty_Sendmail "From: $self->{send_from}?n"; print webliberty_Sendmail "Subject: " . $self->_encode($self->{subject}) . "?n"; if ($files[0]) { print webliberty_Sendmail "Content-Type: multipart/mixed; boundary=?"$boundary?"?n?n"; print webliberty_Sendmail "--$boundary?n"; } print webliberty_Sendmail "Content-Transfer-Encoding: 7bit?n"; print webliberty_Sendmail "Content-Type: text/plain; charset=iso-2022-jp?n?n"; print webliberty_Sendmail "$self->{message}?n"; foreach (@files) { my $file_ins = new webliberty::File($_); my $file_name = $file_ins->get_name . '.' . $file_ins->get_ext; print webliberty_Sendmail "--$boundary?n"; print webliberty_Sendmail "Content-Type: application/octet-stream; name=?"$file_name?"?n"; print webliberty_Sendmail "Content-Transfer-Encoding: X-uuencode?n"; print webliberty_Sendmail "Content-Disposition: attachment; filename=?"$file_name?"?n?n"; if (open(webliberty_Sendmail_FILE, $_)) { binmode(webliberty_Sendmail_FILE); print webliberty_Sendmail $self->_uuencode(join('', <webliberty_Sendmail_FILE>), $file_name); close(webliberty_Sendmail_FILE); } } close(webliberty_Sendmail); return 1; }

    • ベストアンサー
    • CGI
  • ArrayListの初期値の設定の仕方(VB.NET)

    VB.NET2005についての質問です。 ArrayList型の変数の初期値に、プロパティの戻り値を設定することは可能でしょうか。 (つまり、下記の(a)(b)の二行を一行にまとめたい、と考えています) どうぞよろしくお願い致します。 Public Class form1   Dim hoge As New ArrayList  'a)初期値としてClass1.P_hogeを設定したい   hoge = Class1.P_hoge    'b)消したい End Class Public Class Class1   Private Shared _hoge As New ArrayList  'すでに値が格納されているものとする   Public Shared Property P_hoge() As ArrayList      Get    Return _hoge    End Get   End Property End Class