为什么使用类别名?

2022-08-30 15:12:48

我们为什么要使用这个函数?例如:class_alias

Class Test {
 public function __construct(){
   echo "Class initialized"; 
 }
}

class_alias("Test", "AnotherName"); 

$instance = new AnotherName();   # equivalent to $instance = new Test();

根据手册,“别名类与原始类完全相同。

这有什么用?


答案 1

令人惊讶的是,没有人提到为什么要这样做的明显原因:关键字只能在最外围的范围内使用,并且在编译时处理,因此您不能基于某些条件,也不能将其设置为块范围:useuse Some\Class

namespace Foo;
if (!extension_loaded('gd'))
{
    use Images\MagicImage as Image;
}
else
{
    use Images\GdImage as Image;
}
class ImageRenderer
{
    public function __construct(Image $img)
    {}
}

这不起作用:尽管语句位于最外围的范围内,但正如我之前所说,这些导入是在编译时执行的,而不是在运行时执行的。作为结果,此代码的行为就像是这样编写的:use

namespace Foo;
use Images\GdImage as Image;
use Images\MagicImage as Image;

这将产生错误(2个类具有相同的别名...)
但是,作为在运行时调用的函数,因此它可以是块作用域,并且可以用于条件导入:class_alias

namespace Foo;
if (!extension_loaded('gd'))
{
    class_alias('Images\\MagicImage', 'Image');
}
else
{
    class_alias('Images\\GdImage','Image');
}
class ImageRenderer
{
    public function __construct(Image $img)
    {}
}

除此之外,我怀疑它的主要好处是,在PHP 5.3(引入了命名空间)之前编写的所有代码都允许您避免编写如下内容:class_alias

$foo = new My_Lib_With_Pseudo_Name_Spaces_Class();

不必重构整个代码库并创建命名空间,添加几个代码就容易得多:

class_alias('My_Lib_With_Pseudo_Name_Spaces_Class', 'MyClass');

到脚本的顶部,以及一些注释。//TODO: switch to Namespaces

另一个用例可能是在实际将这些类转移到它们的命名空间对应项时:只需在重构一个类后更改调用,其他类就可以保持不变。
在重构代码时,您很可能会想要重新考虑一些事情,因此像aichinm建议的用例可能不会太牵强。class_alias

我能想到的最后一件事,但我还没有看到这一点,当你想用一个模拟对象测试一些代码时,你可以用它来使一切顺利运行。但是,如果您必须这样做,则可能会将测试视为失败,因为这表明代码编写得很糟糕,IMO。class_alias

顺便说一句,就在今天,我遇到了另一个用例。我正在研究一种实现lib的方法,该库是从CLI工具中提取的,用于基于MVC的Web应用程序。一些类依赖于要传递的被调用命令的实例,它们从中获取了一些其他位和螺栓。
我没有经历重构的麻烦,而是决定替换:class_alias

use Application\Commands\SomeCommand as Invoker;

语句包含:

if (\PHP_SAPI === 'cli')
{
    class_alias('\\Application\\Commands\\SomeCommand', 'Invoker');
}
else
{
    class_alias('\\Web\\Models\\Services\\SomeService', 'Invoker');
}

而且,在快速的vim之后,我很高兴(或多或少):%s/SomeCommand/Invoker/g


答案 2

从另一个角度思考这个问题。有一个库,它包含一个名为MySq的类,随着库在开发过程中的推进,他们认为“哦,也许我们应该只做一个数据库类”,所以重写类并将其称为“DatabaseConnection”,它具有与MySql类相同的功能,但它也可以处理Sql和MsSql。随着时间的流逝,他们发布了新版本“PHPLib2”。开发人员现在有两个选项:1,告诉用户从MySql更改为DatabaseConnection或2,开发人员使用

class_alias("DatabaseConnection","MySql"); 

并且只需将类MySql标记为已弃用。

tltr;

保持版本兼容性!


推荐