PHP的__autoload()
(documentation)对我来说非常有趣。以下是它的工作原理:
new Toast_Mitten()
(脚注1)__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! - 您的代码正在使用它
我的问题有两个:
1 我向非英语母语人士道歉。这是一个小笑话。据我所知,没有“吐司手套”这样的东西。如果有的话,这将是一个拿起热吐司的手套。也许你在自己的国家有烤面包手套?
答案 0 :(得分:5)
Ruby和PHP都是从Perl的AUTOLOAD中获取它。
请注意,AutoLoader模块是一组使用AUTOLOAD功能的常见任务助手。
答案 1 :(得分:3)
__autoload()
。它是一个全局的东西,所以根据定义,它有点邪恶。而是使用spl_autoload_register()
向系统注册另一个自动加载器。这允许您使用几个自动加载器,这是非常常见的做法。new MyProject\IO\FileReader();
应该在MyProject/IO/FileReader.php
文件中。 魔法是邪恶的!
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在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点也表明了遵循约定是多么有用,即使你自己创建它们。