12

PHP 的__autoload()文档)对我来说非常有趣。以下是它的工作原理:

  • 您尝试使用一个类,例如new Toast_Mitten()(脚注1
  • 该类尚未加载到内存中。PHP 缩回拳头,让你犯错。
  • 它暂停。“等等,”它说。“__autoload()定义了一个函数。” 它运行它。
  • 在该函数中,您以某种方式将字符串映射Toast_Mittenclasses/toast_mitten.php并告诉它需要该文件。确实如此。
  • 现在该类在内存中,您的程序继续运行。

内存好处:你只加载你需要的类。简洁的好处:您可以停止在任何地方包含如此多的文件,而只需包含您的自动加载器。

事情变得特别有趣,如果

1)您__autoload()有一种从类名中自动确定文件路径和名称的方法。例如,也许您所有的课程都在classes/并且Toast_Mitten将在classes/toast_mitten.php. 或者,也许您将类命名为Animal_Mammal_Weasel,它将位于classes/animal/mammal/animal_mammal_weasel.php.

2)您使用工厂方法来获取类的实例。

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

Mitten::factory 方法可以对自己说,“让我们看看,我有一个名为 的子类Toast_Mitten()吗?如果有,我将返回它;如果没有,我将返回我自己的一个通用实例 - 一个标准的连指手套。哦,看!__autoload()告诉我有一个专门的吐司类。好的,这是一个实例!

因此,您可以开始在整个代码中使用通用手套,当您需要为 toast 提供特殊行为的那一天到来时,您只需创建该类并bam!- 您的代码正在使用它。

我的问题是双重的:

  • 事实)其他语言有类似的结构吗?我看到Ruby 有一个 autoload,但似乎您必须在给定的脚本中指定您希望在哪些类上使用它。
  • 观点)这也太神奇了吧?如果你最喜欢的语言不这样做,你会想,“嘿,漂亮,我们应该有那个”或“我很高兴语言 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() 的子类?如果有,我将返回它;如果没有,我将只返回我自己的一个通用实例 - 一个标准“

    相当棘手的代码,使用简单而冗长的代码:

    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 的模块#const_missing

我刚刚了解到这一点:Ruby 在 Module 上有一个方法调用const_missing,如果你调用它Foo::Bar并且Bar它还没有在内存中(尽管我认为它Foo必须在内存中),它就会被调用。

ruby-doc.org 中的这个示例展示了一种使用它为该模块实现自动加载器的方法。这实际上是 Rails 用来加载新的 ActiveRecord 模型类的方法,根据 Russ Olsen 的“Eloquent Ruby”(第 21 章,“使用 method_missing 进行灵活的错误处理”,其中也包括const_missing)。

它之所以能够做到这一点,是因为“约定优于配置”的心态:如果您引用一个名为 的模型ToastMitten,如果它存在,它将位于app/models/toast_mitten.rb. 如果您可以将该模型放在您想要的任何地方,Rails 将不知道在哪里寻找它。即使您没有使用 Rails,这个示例和我的问题中的第 1 点也显示了遵循约定是多么有用,即使您自己创建它们也是如此。

于 2010-11-15T16:38:01.270 回答