我想创建一个类的实例,并在一行代码中调用该实例上的方法.
PHP不允许在常规构造函数上调用方法:
new Foo()->set_sth(); // Outputs an error.
Run Code Online (Sandbox Code Playgroud)
所以我正在使用,如果我可以称之为静态构造函数:
Foo::construct()->set_sth();
Run Code Online (Sandbox Code Playgroud)
这是我的问题:
使用像这样的静态构造函数是一种很好的实践,如果是的话,你会如何为这些静态构造函数命名方法?
我一直在犹豫以下选项:
Foo::construct();
Foo::create();
Foo::factory()
Foo::Foo();
constructor::Foo();
Run Code Online (Sandbox Code Playgroud)
koe*_*oen 11
任何方法的命名都应该有意图揭示名称.我不知道'Foo :: factory'是做什么的.尝试构建更高级别的语言:
User::with100StartingPoints();
Run Code Online (Sandbox Code Playgroud)
这将是:
$user = new User();
$user->setPointsTo(100);
Run Code Online (Sandbox Code Playgroud)
您还可以轻松测试User :: with100StartingPoints()是否与此相等.
正如@koen所说,静态构造函数(或"命名构造函数")仅有助于证明其意图.
从5.4开始,出现了一些名为"dereferencing"的东西,它允许你直接用方法调用来内联类实例化.
(new MyClass($arg1))->doSomething(); // works with newer versions of php
Run Code Online (Sandbox Code Playgroud)
因此,只有在有多种方法实例化对象时,静态构造函数才有用.如果只有一个(总是相同类型的参数和args数),则不需要静态构造函数.
但是如果你有多种实例化方法,那么静态构造函数非常有用,因为它避免了使用无用的参数检查污染你的主构造函数,削弱语言约束.
例:
<?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;
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见oneDayStartingToday,静态方法可以访问实例的私有字段!疯了不是吗?:)
有关更好的解释,请参阅http://verraes.net/2014/06/named-constructors-in-php/
如果你不需要对新构造的引用Foo,为什么不简单地创建set_sth一个static函数(Foo如果需要的话,让它在内部创建一个新函数)?
如果你确实需要掌握参考,你会怎么做?return $this在set_sth?但set_sth无论如何都可以制成工厂功能.
我能想到的唯一情况是,如果要在一个表达式中对新构造的实例调用可链接方法(如在流畅的界面中).那是你想要做的吗?
无论如何,您可以为所有类型的对象使用通用工厂函数,例如
function create_new($type) {
return new $type;
}
create_new('Foo')->set_sth();
Run Code Online (Sandbox Code Playgroud)
它可能不是最佳实践,但您可以使用函数和类具有两个不同命名空间的事实:您可以拥有一个与类同名的函数.
这允许人们编写这种代码,例如:
function MyClass() {
return new MyClass();
}
class MyClass {
public function __construct() {
$this->a = "plop";
}
public function test() {
echo $this->a;
}
protected $a;
}
Run Code Online (Sandbox Code Playgroud)
请注意,我已经定义了一个名为的函数MyClass,以及一个具有相同名称的类.
然后,你可以这样写:
MyClass()->test();
Run Code Online (Sandbox Code Playgroud)
这将完美地工作,并没有给你任何错误 - 在这里,你将得到以下输出:
plop
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
35586 次 |
| 最近记录: |