php 静态构造函数的最佳实践
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5368199/
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
Best practices for static constructors
提问by Emanuil Rusev
I want to create an instance of a class and call a method on that instance, in a single line of code.
我想在一行代码中创建一个类的实例并在该实例上调用一个方法。
PHP won't allow calling a method on a regular constructor:
PHP 不允许在常规构造函数上调用方法:
new Foo()->set_sth(); // Outputs an error.
So I'm using, if I can call it that, a static constructor:
所以我正在使用,如果我可以称之为静态构造函数:
Foo::construct()->set_sth();
Here's my question:
这是我的问题:
Is using static constructors like that considered a good practice and if yes, how would you recommend naming the methods for these static constructors?
使用这样的静态构造函数是否被认为是一种好习惯,如果是,您会如何建议为这些静态构造函数命名方法?
I've been hesitating over the following options:
我一直在犹豫以下选项:
Foo::construct();
Foo::create();
Foo::factory()
Foo::Foo();
constructor::Foo();
回答by koen
The naming of any method should be with intention revealing names. I can't tell what 'Foo::factory' does. Try to build to a higher level language:
任何方法的命名都应该有意揭示名称。我不知道 'Foo::factory' 做了什么。尝试构建到更高级别的语言:
User::with100StartingPoints();
This would be the same as:
这将与以下内容相同:
$user = new User();
$user->setPointsTo(100);
You could also easily test whether User::with100StartingPoints() is equal to this.
您还可以轻松测试 User::with100StartingPoints() 是否等于 this。
回答by Florian Klein
Static constructors (or "named constructors") are only beneficial to prove an intention, as @koen says.
正如@koen 所说,静态构造函数(或“命名构造函数”)仅有助于证明意图。
Since 5.4 though, someting called "dereferencing" appeared, which permits you to inline class instantiation directly with a method call.
但是,从 5.4 开始,出现了称为“取消引用”的东西,它允许您直接使用方法调用内联类实例化。
(new MyClass($arg1))->doSomething(); // works with newer versions of php
So, static constructors are only useful if you have multiple ways to instantiate your objects. If you have only one (always the same type of arguments and number of args), there is no need for static constructors.
因此,静态构造函数仅在您有多种方法来实例化对象时才有用。如果您只有一个(始终相同类型的参数和数量的参数),则不需要静态构造函数。
But if you have multiple ways of instantiations, then static constructors are very useful, as it avoids to pollute your main constructor with useless argument checking, weakening languages constraints.
但是如果你有多种实例化方式,那么静态构造函数就非常有用,因为它避免了无用的参数检查污染你的主构造函数,削弱了语言的约束。
Example:
例子:
<?php
class Duration
{
private $start;
private $end;
// or public depending if you still want to allow direct instantiation
private function __construct($startTimeStamp = null, $endTimestamp = null)
{
$this->start = $startTimestamp;
$this->end = $endTimestamp;
}
public static function fromDateTime(\DateTime $start, \DateTime $end)
{
return new self($start->format('U'), $end->format('U'));
}
public static function oneDayStartingToday()
{
$day = new self;
$day->start = time();
$day->end = (new \DateTimeImmutable)->modify('+1 day')->format('U');
return $day;
}
}
As you can see in oneDayStartingToday
, the static method can access private fields of the instance! Crazy isn't it ? :)
正如你在 中看到的oneDayStartingToday
,静态方法可以访问实例的私有字段!是不是疯了?:)
For a better explanation, see http://verraes.net/2014/06/named-constructors-in-php/
有关更好的解释,请参阅http://verraes.net/2014/06/named-constructors-in-php/
回答by Jon
If you don't need a reference to the newly constructed Foo
, why don't you simply make set_sth
a static
function (and have it create a new Foo
internally if required)?
如果您不需要对新构造的引用Foo
,为什么不简单地创建set_sth
一个static
函数(Foo
如果需要,让它在内部创建一个新函数)?
If you doneed to get hold of the reference, how would you do it? return $this
in set_sth
? But then set_sth
can be made into a factory function anyway.
如果您确实需要获取参考资料,您会怎么做?return $this
在set_sth
?但是set_sth
无论如何都可以做成工厂函数。
The only situation I can think of is if you want to call chainable methods (like in a fluent interface) on a newly constructed instance all in one expression. Is that what you are trying to do?
我能想到的唯一情况是,如果您想在一个表达式中在新构造的实例上调用可链接的方法(如在流畅的接口中)。这就是你想要做的吗?
Anyway, you can use a general-purpose factory function for all types of objects, e.g.
无论如何,您可以对所有类型的对象使用通用工厂函数,例如
function create_new($type) {
return new $type;
}
create_new('Foo')->set_sth();
回答by Pascal MARTIN
It's probably not quite a best practice, but you could use the fact that functions and classes have two different namespaces : you can have a function that have the same name as a class.
这可能不是最佳实践,但您可以使用函数和类具有两个不同命名空间的事实:您可以拥有与类同名的函数。
This allows one to write this kind of code, for example :
这允许人们编写这种代码,例如:
function MyClass() {
return new MyClass();
}
class MyClass {
public function __construct() {
$this->a = "plop";
}
public function test() {
echo $this->a;
}
protected $a;
}
Note that I have defined a function called MyClass
, and a class with the same name.
请注意,我定义了一个名为 的函数MyClass
和一个同名的类。
Then, you can write this :
然后,你可以这样写:
MyClass()->test();
Which will work perfectly, and not get you any error -- here, you'll get the following output :
这将完美运行,并且不会给您带来任何错误 - 在这里,您将获得以下输出:
plop
回答by David Harkness
These are called creation methods, and I typically name them createXXX()
such as createById()
or createEmptyCatalog()
. Not only do they provide a nice way to reveal the different intentions of an object's constructors, but they enable immediate method chaining in a fluent interface.
这些称为创建方法,我通常将它们命名createXXX()
为createById()
或createEmptyCatalog()
。它们不仅提供了一种很好的方式来揭示对象构造函数的不同意图,而且还支持在流畅的接口中立即链接方法。
echo Html_Img::createStatic('/images/missing-image.jpg')
->setSize(60, 90)
->setTitle('No image for this article')
->setClass('article-thumbnail');
回答by NikiC
Addition to Jon's answer: To allow constructor arguments use the following:
除了Jon 的回答:要允许构造函数参数使用以下内容:
function create($type) {
$args = func_get_args();
$reflect = new ReflectionClass(array_shift($args));
return $reflect->newInstanceArgs($args);
}
create('Foo', 'some', 'args')->bar();
Documentation: ReflectionClass
->
newInstanceArgs
回答by Hezuo
Propel uses a static method "create". I'd go with that. This method makes the code easier to test rather than just using static methods to perform business logic.
Propel 使用静态方法“create”。我愿意。这种方法使代码更易于测试,而不仅仅是使用静态方法来执行业务逻辑。
<?php
class MyClass
{
public static function create()
{
return new MyClass();
}
public function myMethod()
{
}
}
Besides, you can also pass parameters to the constructor. For instance:
此外,您还可以将参数传递给构造函数。例如:
<?php
class MyClass
{
public function __construct($param1, $param2)
{
//initialization using params
}
public static function create($param1, $param2)
{
return new MyClass($param1, $param2); // return new self($param1, $param2); alternative ;)
}
public function myMethod()
{
}
}
In either case, you'd be able to invoke myMethod right after the create method
无论哪种情况,您都可以在 create 方法之后立即调用 myMethod
<?php
MyClass::create()->myMethod();
// or
MyClass::create($param1, $param2)->myMethod();
回答by Jose Ananio
A bit late to the party but I think this might help.
聚会有点晚了,但我认为这可能会有所帮助。
class MyClass
{
function __construct() {
// constructor initializations here
}
public static myMethod($set = null) {
// if myclass is not instantiated
if (is_null($set)) {
// return new instance
$d = new MyClass();
return $d->Up('s');
} else {
// myclass is instantiated
// my method code goes here
}
}
}
this can then be used as
这可以用作
$result = MyClass::myMethod();
optional parameters can be passed through either the __constructor or myMethod.
This is my first post and I hope I got the gimmicks right
可选参数可以通过 __constructor 或 myMethod 传递。
这是我的第一篇文章,我希望我的噱头是对的