是否可以动态扩展类?
我有一个类,我需要根据标准使用它来扩展不同的类(最多数百个)。 PHP 有没有办法通过动态类名来扩展类?
我认为它需要一种方法来指定带有实例化的扩展。
有想法吗?
I have a class which I need to use to extend different classes (up to hundreds) depending on criteria. Is there a way in PHP to extend a class by a dynamic class name?
I assume it would require a method to specify extension with instantiation.
Ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
你不能只使用 eval 吗?
Couldn't you just use an eval?
我已经解决了我的同样类型的问题。第一个参数定义原始类名,第二个参数定义class_alias函数的新类名。然后我们可以在 if 和 else 条件下使用这个函数。
Apple 类扩展为虚拟类“C”,根据 if 和 else 条件,可以将其定义为类“A”或“B”。
有关更多信息,您可以查看此链接 https://www.php.net /manual/en/function.class-alias.php
I have solved my same type of problem. The first parameter defines the original class name and the second parameter defines the new class name of class_alias function. Then we can use this function in if and else condition.
Apple class extends to virtual class "C" which can be defined as class "A" Or "B" depend on if and else condition.
For More information you can check this link https://www.php.net/manual/en/function.class-alias.php
类 myClass {
公共$parentVar;
函数 __construct() {
$all_classes = get_declared_classes(); // 所有类
$parent = $parent[count($parent) -2]; //-2是位置
$this->parentVar = new $parent();
}
}
class myClass {
public $parentVar;
function __construct() {
$all_classes = get_declared_classes(); // all classes
$parent = $parent[count($parent) -2]; //-2 is the position
$this->parentVar = new $parent();
}
}
我的想法很简单,你可以试试
I have an idea so simple, you can try
我必须使用扩展两个抽象类之一的处理器类来完成此操作。
工作解决方案如下所示:
如果抽象父类包含抽象方法,则不需要在任何动态父类中实现它们。
如果您正在处理一个大型项目,您可能不想使用 DynamicParent 作为类名,除非这些类是命名空间的。您需要更具体的东西来避免冲突。
I had to do this with a processor class that extends one of two abstract classes.
The working solution looks like this:
If the abstract parent classes contain abstract methods, they don't need to be implemented in either of the dynamic parent classes.
If you're working on a large project, you probably don't want to use DynamicParent as the class name unless the classes are namespaced . You'll need something more specific to avoid collisions .
虽然这仍然不可能,也不完全是你的答案,但我需要同样的东西,并且不想使用 eval、monkey-patching 等。所以我通过在条件中扩展它来使用默认类。
当然,这意味着如果您有 100 个类要扩展,您需要通过另一个扩展操作添加 100 个条件,但对我来说,这看起来是正确的方法。
While it's still not possible and not exactly your answer i needed the same thing and didn't wanted to use eval, monkey-patching etc. So i used a default class by extending it in conditions.
Of course it means if you have 100 classes to extend you need to add 100 conditions with another extending operation but for me this looked like the right way.
是的。我喜欢 eval 的答案,但很多人害怕代码中的任何 eval,所以这是一个没有 eval 的答案:
Yes. I like the answer with eval, but a lot of people afraid of any eval in their code, so here's one with no eval:
可以使用神奇的 __call 函数的强大功能在 PHP 中创建动态继承。它需要一些基础设施代码才能工作,但并不是太令人畏惧。
免责声明
在使用此技术之前,您确实应该至少三思而后行,因为这实际上是一件坏事。
我使用此技术的唯一原因是因为我不想在为站点创建模板时创建接口定义或设置依赖项注入。我希望能够在模板中定义几个函数“块”,然后让继承自动使用正确的“块”。
实现
所需的步骤是:
子类现在扩展了“DynamicExtender”类。该类拦截子类对子类中不存在的方法进行的任何调用,并将它们重定向到父实例。
每个“ParentClass”都扩展为“ProxyParentClass”。对于父类中的每个可访问方法,“ProxyParentClass”中都存在等效方法。 “ProxyParentClass”中的每个方法都会检查该方法是否存在于 ChildClass 中,如果存在,则调用该函数的子版本,否则调用 ParentClass 中的版本
当构造 DynamicExtender 类时,您传入当您需要什么父类时,DynamicExtender 创建该类的一个新实例,并将其自身设置为 ParentClass 的子类。
因此,现在当我们创建子对象时,我们可以指定所需的父类,DynamicExtender 将为我们创建它,并且子类看起来像是从我们在运行时请求的类扩展而来,而不是很难-编码。
这可能更容易理解为几个图像:
固定继承是固定的
使用代理的动态继承
演示实现
此解决方案的代码为 可在 Github 上获取 以及关于如何这里可以使用,但是上图的代码是:
It is possible to create dynamic inheritance in PHP using the power of the magic __call function. It takes a little bit of infrastructure code to work but isn't too daunting.
Disclaimer
You really ought to think at least twice before using this technique as it's actually kind of bad thing to do.
The only reason I'm using this technique is because I don't want to have to either create the interface definitions or setup the dependency injections when creating templates for a site. I want to just be able to just define a couple of function 'blocks' in a template and then have inheritance automatically use the correct 'block'.
Implementation
The steps required are:
The child class now extends a 'DynamicExtender' class. This class intercepts any calls made by the child class, to methods that don't exist in the child class and redirects them to the parent instance.
Each 'ParentClass' is extended to a 'ProxyParentClass'. For every accessible method in the parent class, there exists an equivalent method in the 'ProxyParentClass'. Each of those methods in the 'ProxyParentClass' checks to see if the method exists in the ChildClass and calls the childs version of the function if it exists, otherwise it calls the version from ParentClass
When the DynamicExtender class is constructed you pass in what parent class you require, the DynamicExtender creates a new instance of that class, and sets itself as the child of the ParentClass.
So, now when we create the child object we can specify the parent class required and the DynamicExtender will create it for us, and it will appear as if the child class is extended from the class we requested at run-time rather than it being hard-coded.
This may be easier to understand as a couple of images:
Fixed inheritance is fixed
Dynamic inheritance with proxies
Demo implementation
The code for this solution is available on Github and a slightly fuller explanation of how this can be used here, but the code for the above image is:
我认为不可能动态扩展一个类(但是,如果我错了,我很想看看它是如何完成的)。您是否考虑过使用复合模式(http://en.wikipedia.org/wiki/Composite_pattern,http://devzone.zend.com/article/7)?您可以动态地组合另一个类(甚至多个类 - 这通常用作多重继承的解决方法),以将父类的方法/属性“注入”到子类中。
I don't think it's possible to dynamically extend a class (however if I'm wrong I'd love to see how it's done). Have you thought about using the Composite pattern (http://en.wikipedia.org/wiki/Composite_pattern, http://devzone.zend.com/article/7)? You could dynamically composite another class (even multiple classes - this is often used as a work around to multiple inheritance) to 'inject' the methods/properties of your parent class into the child class.