php 从静态方法中创建类实例
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4658537/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Create class instance from within static method
提问by daniel
As the title says, I'm wanting to create an instance of a class from within a static method of the same class. I've figured out so far is that I can by doing something like this:
正如标题所说,我想从同一个类的静态方法中创建一个类的实例。到目前为止,我发现我可以通过做这样的事情:
class Foo{
public $val;
public static function bar($val){
$inst = new Foo;
$inst->val = $val;
return $inst;
}
}
Which therefore lets me do this.
因此,这让我可以这样做。
$obj = Foo::bar("some variable");
Which is great.
这很棒。
So now the questions. Is there an easier way of doing this that I'm not aware of, or any shortcuts to achieving the same result? Are there any advantages or disadvantages of creating an instance in this fashion?
所以现在的问题。有没有我不知道的更简单的方法来做到这一点,或者有什么捷径可以达到同样的结果?以这种方式创建实例有什么优点或缺点吗?
Thanks.
谢谢。
回答by ircmaxell
They way you're doing it is fine. There are a few other things that can make your life easier that you can do as well.
你这样做的方式很好。还有一些其他事情可以让您的生活更轻松,您也可以这样做。
Don't hardcode the class name. If you're on 5.3+, use the keyword
static
. That way, if you extend the class, the new function can instantiate that one as well:public static function bar($var) { $obj = new static(); $obj->var = $var; return $obj; }
Then you can use it in any extending class without needing to override anything.
Figure out if
$var
should be passed in through a constructor rather than set after construction. If the object depends upon it, you should require it.public function __construct($var) { $this->var = $var; }
That way you can't instantiate the object without setting the variable.
Enforce the instantiation of the class through the static method. If you're doing anything in there that you need to do, then make the constructor either protected or private. That way, someone can't bypass the static method.
protected function __construct() {} private function __construct() {}
不要对类名进行硬编码。如果您使用的是 5.3+,请使用关键字
static
。这样,如果您扩展该类,新函数也可以实例化该类:public static function bar($var) { $obj = new static(); $obj->var = $var; return $obj; }
然后您可以在任何扩展类中使用它而无需覆盖任何内容。
弄清楚是否
$var
应该通过构造函数传入而不是在构造之后设置。如果对象依赖于它,你应该要求它。public function __construct($var) { $this->var = $var; }
这样你就不能在不设置变量的情况下实例化对象。
通过静态方法强制实例化类。如果你在那里做任何你需要做的事情,那么让构造函数成为受保护的或私有的。这样,有人就无法绕过静态方法。
protected function __construct() {} private function __construct() {}
I hope that helps...
我希望这有帮助...
Edit:Based on your comment above, it sounds to me like you're trying to implement the Singleton Design Pattern. There's tons of information out there about why it's not a great idea and the bad things it may do. It has uses as well.
编辑:根据您上面的评论,在我看来,您似乎正在尝试实施Singleton Design Pattern。有大量关于为什么它不是一个好主意以及它可能会做的坏事的信息。它也有用途。
But there are a few other patterns that may be of use to you depending on what you're doing exactly.
但是还有一些其他模式可能对您有用,具体取决于您正在做什么。
- You can use the Factory Methodif you're trying to create different objects using the same steps.
- If all of the objects start off the same and then are customized, you could use the Prototype Pattern.
- You could use an Object Poolif it's particularly expensive to create your object.
- 如果您尝试使用相同的步骤创建不同的对象,则可以使用工厂方法。
- 如果所有对象都以相同的方式开始,然后进行自定义,则可以使用Prototype Pattern。
- 如果创建对象的成本特别高,则可以使用对象池。
But one thing to consider, is that in PHP objects are pretty light weight. Don't try to avoid creating a new object just for that overhead. Avoid doing heavy things like database queries or filesystem accesses multiple times. But don't worry about calling new Foo()
unless foo
's constructor is particularly heavy...
但要考虑的一件事是,在 PHP 中对象的重量非常轻。不要试图避免仅为该开销创建新对象。避免多次执行诸如数据库查询或文件系统访问之类的繁重事情。但是不要担心调用,new Foo()
除非foo
的构造函数特别重......
回答by Pedro Loureiro
This looks like a simple factory method pattern.
这看起来像一个简单的工厂方法模式。
You have a nice advantage: suppose that in the future you want to start using a different implementation (but that does the same thing). Using a factory you can change all the objects that are created in many places of a complex system simply by changing the creator method. Note that this would work easier if you used an external class (as is in the first link below).
你有一个很好的优势:假设将来你想开始使用不同的实现(但它做同样的事情)。使用工厂,您可以简单地通过更改创建者方法来更改在复杂系统的许多地方创建的所有对象。请注意,如果您使用外部类(如下面的第一个链接所示),这会更容易。
Keeping it as you have now, you can also subclass this class and override the method to create a more complex object. I don't think this is what you want to achieve in here.
保持它现在的样子,您还可以子类化此类并覆盖该方法以创建更复杂的对象。我不认为这是你想要在这里实现的目标。
Anyway, this is good to enable Test Driven Development, abstraction and lots of other good things.
无论如何,这对于启用测试驱动开发、抽象和许多其他好东西是很好的。
links:
链接:
回答by john-raymon
Super late but found this useful.
超级晚,但发现这很有用。
A good example of this in the wild is this static method from Audi's UI library returning an Array
of instantiated TextField
classes from within TextField
's static
method upgradeElements
.
一个很好的例子是来自 Audi 的 UI 库的这个静态方法,它从内部的方法中返回一个Array
实例化的TextField
类。TextField
static
upgradeElements
/**
* Class constructor for Textfield AUI component.
* Implements AUI component design pattern defined at:
* https://github.com/...
*
* @param {HTMLElement} element The element that will be upgraded.
*/
export default class Textfield extends Component {
/**
* Upgrades all Textfield AUI components.
* @returns {Array} Returns an array of all newly upgraded components.
*/
static upgradeElements() {
let components = [];
Array.from(document.querySelectorAll(SELECTOR_COMPONENT)).forEach(element => {
if (!Component.isElementUpgraded(element)) {
components.push(new Textfield(element));
}
});
return components;
};
constructor(element) {
super(element);
}
...
See the rest in the repo https://github.com/audi/audi-ui/blob/master/src/textfield/textfield.js#L25
查看 repo 中的其余部分 https://github.com/audi/audi-ui/blob/master/src/textfield/textfield.js#L25
回答by Nanne
If you're just creating an object, this isn't very usefull. You could just call a constructor. But if you're doing something more complicated (like you're starting with some sort of singleton pattern but haven't included all the details in this example), then:
如果你只是创建一个对象,这不是很有用。你可以只调用一个构造函数。但是如果你正在做一些更复杂的事情(比如你从某种单例模式开始,但没有在这个例子中包含所有细节),那么:
This sounds about right. If you want to prevent objects created in the default way like this:
这听起来是对的。如果你想阻止像这样以默认方式创建的对象:
$obj = new Foo("Some Variable");
You can add a private constructor:
您可以添加一个私有构造函数:
class Foo{
public $val;
private __construct(){}
public static function bar($val){
$inst = new Foo;
$inst->val = $val;
return $inst;
}
}
Now you enforce people to use your static class. The need to set the val in the function might be gone, so you could even add the value-parameter to your private constructor but do the other things (that you presumably want to do, like check for some sort of singleton pattern) in your 'bar' function
现在你强制人们使用你的静态类。在函数中设置 val 的需要可能会消失,因此您甚至可以将值参数添加到您的私有构造函数中,但在您的“酒吧”功能