PHP的__autoload()有多独特?

时间:2010-10-19 09:23:19

标签: php ruby language-agnostic language-features autoload

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

  • 您尝试使用类new Toast_Mitten()(脚注1
  • 该类尚未加载到内存中。 PHP拉回拳头,给你带来了错误。
  • 它停顿了一下。 “等等,”它说。 “定义了__autoload()函数。”它运行它。
  • 在该函数中,您以某种方式将字符串Toast_Mitten映射到classes/toast_mitten.php并告诉它要求该文件。它确实。
  • 现在班级在内存中,你的程序一直在运行。

内存优势:您只需加载所需的类。 Terseness的好处:您可以停止在任何地方包含这么多文件,只需包含您的自动加载器。

如果

,事情会变得特别有趣

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 has an autoload,但似乎您必须在给定的脚本中指定您希望使用哪些类。
  • 意见)这太神奇了吗?如果你最喜欢的语言没有这样做,你认为,“嘿嘿,我们应该有那个”或“我很高兴语言X不是那么草率?”

1 我向非英语母语人士道歉。这是一个小笑话。据我所知,没有“吐司手套”这样的东西。如果有的话,这将是一个拿起热吐司的手套。也许你在自己​​的国家有烤面包手套?

5 个答案:

答案 0 :(得分:5)

Ruby和PHP都是从Perl的AUTOLOAD中获取它。

请注意,AutoLoader模块是一组使用AUTOLOAD功能的常见任务助手。

答案 1 :(得分:3)

  1. 请勿使用__autoload()。它是一个全局的东西,所以根据定义,它有点邪恶。而是使用spl_autoload_register()向系统注册另一个自动加载器。这允许您使用几个自动加载器,这是非常常见的做法。
  2. 尊重现有惯例。 namespaced 类名的每个部分都是一个目录,因此new MyProject\IO\FileReader();应该在MyProject/IO/FileReader.php文件中。
  3. 魔法是邪恶的!

      

    Mitten :: factory方法可以对自己说,“让我们看看,我有一个名为Toast_Mitten()的子类吗?如果有,我会返回;如果没有,我只会返回一个我自己的通用实例 - 一个标准的手套。哦,看!__ autoload()告诉我烤面包有一个特殊的类。好的,这是一个实例!“

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

    try {
        $mitten = new ToastMitten();
        // or $mitten = Mitten::factory('toast');
    } catch (ClassNotFoundException $cnfe) {
        $mitten = new BaseMitten();
    }
    

答案 2 :(得分:1)

我认为这个功能非常方便,我还没有看到任何其他功能。我也不需要这些功能。

答案 3 :(得分:1)

Java有类似的东西。它被称为ClassLoader。可能也是其他语言,但他们坚持一些默认实现。

而且,虽然我们在这。如果__autoload加载任何类型的符号,而不仅仅是类:常量,函数和类,那将是很好的。

答案 4 :(得分:1)

参见Ruby的模块#const_missing

我刚学会了这一点:Ruby在Module上有一个名为const_missing的方法,如果你调用Foo::Bar并且Bar尚未在内存中,则会调用该方法(尽管我认为{{ 1}}必须在记忆中。)

This example in ruby-doc.org显示了一种使用该方法为该模块实现自动加载器的方法。事实上,根据Russ Olsen的“Eloquent Ruby”(第21章“使用method_missing进行灵活的错误处理”,也包含Foo),Rails用来加载新的ActiveRecord模型类。

由于“约定优于配置”的思维模式,它能够做到这一点:如果你引用一个名为const_missing的模型,如果它存在,它将在ToastMitten中。如果您可以将该模型放在任何您想要的位置,Rails就不知道在哪里寻找它。即使你没有使用Rails,这个例子和我的问题中的#1点也表明了遵循约定是多么有用,即使你自己创建它们。