12

PHP __autoload()ドキュメント)は私にとって非常に興味深いものです。仕組みは次のとおりです。

  • new Toast_Mitten()(脚注1)のようなクラスを使おうとします
  • クラスがメモリにロードされていません。PHPはその拳を引き戻して、エラーであなたを悩ませます。
  • 一時停止します。「待って」とそれは言います。「__autoload()関数が定義されています。」それを実行します。
  • その関数では、文字列Toast_Mittenを何らかの方法でマップclasses/toast_mitten.phpし、そのファイルを要求するように指示しました。します。
  • これでクラスはメモリ内にあり、プログラムは実行を続けます。

メモリの利点:必要なクラスのみをロードします。簡潔さの利点:どこにでも非常に多くのファイルを含めるのをやめ、オートローダーを含めるだけで済みます。

物事は特に興味深いものになります

1)__autoload()クラス名からファイルパスと名前を自動的に決定する方法があります。たとえば、すべてのクラスがにclasses/あり、Toast_Mittenになりますclasses/toast_mitten.phpAnimal_Mammal_Weaselまたは、のようなクラスに名前を付けることもできますclasses/animal/mammal/animal_mammal_weasel.php

2)ファクトリメソッドを使用してクラスのインスタンスを取得します。

$Mitten = Mitten::factory('toast');

Mitten :: factoryメソッドは、「見てみましょう。サブクラスという名前がありToast_Mitten()ますか?そうでない場合は、それを返します。そうでない場合は、自分のジェネリックインスタンス(標準のミトン)を返します。ああ、見て!トースト用の特別なクラスがあると__autoload()教えてくれます。OK、これがインスタンスです!」

したがって、コード全体で一般的なミトンの使用を開始できます。トーストに特別な動作が必要になる日が来たら、そのクラスとバムを作成するだけです。-あなたのコードはそれを使用しています。

私の質問は2つあります:

  • 事実)他の言語にも同様の構成がありますか?Rubyには自動ロードがあるようですが、特定のスクリプトで、Rubyを使用する予定のクラスを指定する必要があるようです。
  • 意見)これは魔法すぎますか?あなたの好きな言語がこれをしないなら、あなたは「ちょっと気の利いた、私たちはそれを持っているべきです」または「私は言語Xがそれほどずさんではないことを嬉しく思います」と思いますか?

1 英語を母国語としない人に謝罪します。これは小さな冗談です。私の知る限り、「トーストミトン」のようなものはありません。もしあれば、それは熱いトーストを拾うためのミトンでしょう。おそらくあなたはあなたの国でトーストミトンを持っていますか?

4

5 に答える 5

5

RubyとPHPはどちらも、PerlのAUTOLOADから取得します。

AutoLoaderモジュールは、AUTOLOAD機能を使用する一般的なタスクのヘルパーのセットであることに注意してください。

于 2010-10-19T11:16:43.317 に答える
3
  1. 使用しないでください__autoload()。それはグローバルなものなので、定義上、それはやや悪です。代わりに、を使用spl_autoload_register()してさらに別のオートローダーをシステムに登録します。これにより、いくつかのオートローダーを使用できるようになります。これはかなり一般的な方法です。
  2. 既存の規則を尊重します。名前空間化されたクラス名のすべての部分はディレクトリであるためnew MyProject\IO\FileReader();、ファイルに含める必要がありMyProject/IO/FileReader.phpます。
  3. 魔法は邪悪です!

    Mitten :: factoryメソッドは、「見てみましょう。Toast_Mitten()というサブクラスがありますか?ある場合はそれを返します。そうでない場合は、自分自身のジェネリックインスタンス(標準)を返します。ミトン。ああ、見て!__autoload()は、トースト用の特別なクラスがあることを教えてくれます。OK、これがインスタンスです!」

    そのようなトリッキーなコードではなく、単純で冗長なコードを使用してください。

    try {
        $mitten = new ToastMitten();
        // or $mitten = Mitten::factory('toast');
    } catch (ClassNotFoundException $cnfe) {
        $mitten = new BaseMitten();
    }
    
于 2010-10-19T11:19:39.283 に答える
1

この機能は非常に便利だと思いますが、他の場所でこのような機能は見たことがありません。また、これらの機能は他の場所では必要ありません。

于 2010-10-19T09:30:15.860 に答える
1

Javaにも似たようなものがあります。それはと呼ばれClassLoaderます。おそらく他の言語もそうですが、それらはいくつかのデフォルトの実装に固執しています。

そして、私たちがこれにいる間。__autoloadクラスだけでなく、定数、関数、クラスなど、任意のタイプのシンボルをロードできればよかったと思います。

于 2010-10-19T09:40:13.107 に答える
1

RubyのModule#const_missingを参照してください

私はこれを学びました:Rubyには、const_missing呼び出したときに呼び出されFoo::BarBarまだメモリにないというモジュールのメソッドがあります(ただし、メモリにある必要があると思いFooます)。

ruby-doc.orgのこの例は、それを使用してそのモジュールのオートローダーを実装する方法を示しています。これは、Russ Olsenによる「EloquentRuby」(第21章「柔軟なエラー処理にmethod_missingを使用する」、これもカバーしていますconst_missing)によると、Railsが新しいActiveRecordモデルクラスをロードするために実際に使用するものです。

「設定より規約」の考え方により、これを行うことができます。と呼ばれるモデルを参照するToastMitten場合、存在する場合は、になりますapp/models/toast_mitten.rb。そのモデルを好きな場所に置くことができれば、Railsはそれを探す場所を知りません。Railsを使用していない場合でも、この例と私の質問のポイント1は、自分で作成した場合でも、規則に従うことがどれほど役立つかを示しています。

于 2010-11-15T16:38:01.270 に答える