我正在转换PHP 5.3库以在PHP 5.2上工作.支持我的主要方法是使用后期静态绑定return new static($options);,如果我将其转换为return new self($options)将得到相同的结果?
new self和之间有什么区别new static?
为什么有些人创建一个返回new static而不是将所有方法设为静态的方法?使用该方法返回新静态的原因是什么?我不是问静态和自我之间有什么区别,或者静态和自我意味着什么.例如,这是一个简单的类:
<?php
class Expression
{
public static function make()
{
return new static;
}
public function find($value)
{
return '/' . $value .'/';
}
public function then($value)
{
return $this->find($value);
}
public function hi($value)
{
return "hi";
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,有一个静态方法make()返回新的静态.然后,有些人会调用其他方法:
$regex = Expression::make()->find('www');
Run Code Online (Sandbox Code Playgroud)
它的目的是什么?我看到在这里我们不使用新的表达式语法,如果这是重点 - 那么为什么他们没有使所有方法成为例如静态?有什么区别,有什么理由让这个方法返回新的静态?
大多数PHP IDE依靠phpdoc来获取有关表达式类型的提示.然而,我经常使用这种模式,似乎没有涵盖:
class Control {
private $label = '';
/** @return ??? */
public static function Make(){ return new static(); }
/** @return ??? */
public function WithLabel($value){ $this->label = $value; return $this; }
/** @return void */
public function Render(){ /* ... */ }
}
class Textbox extends Control {
private $text = '';
/** @return ??? */
public function WithText($text){ $this->width = $text; return $this; }
}
Run Code Online (Sandbox Code Playgroud)
现在我可以使用这样的类:
Textbox::Make() // <-- late static binding, returns Textbox
->WithLabel('foo') // …Run Code Online (Sandbox Code Playgroud) 从5.3版开始,PHP支持静态方法的后期绑定.虽然这是一个无疑是有用的功能,但只有几种情况需要使用它(例如Active Record模式).
考虑这些例子:
1.便利施工人员(::create())
class SimpleObject
{
public function __construct() { /* ... */ }
public static function create()
{
return new static; // or: return new self;
}
}
Run Code Online (Sandbox Code Playgroud)
如果这个类可能被扩展(但是,它没有被同一个包中的任何类扩展),那么应该使用延迟静态绑定来使它更容易扩展(无需重写::create()方法,更重要的是,不必记住要做到这一点)?
注意:这个习惯用于解决在构造对象上调用方法的不可能性:new SimpleObject()->doStuff()在PHP中无效.
2.类常数
class TagMatcher
{
const TAG_PATTERN = '/\<([a-z\-]+?)\>/i';
private $subject;
public function construct($subject) { $this->subject = $subject; }
public function getAllTags()
{
$pattern = static::TAG_PATTERN;
preg_match_all($pattern, $this->subject);
return $pattern[1];
}
}
Run Code Online (Sandbox Code Playgroud)
static::在此示例中使用的原因与前一个类似.它的使用只是因为这个类可以通过扩展它并覆盖常量来匹配不同形式的标签.
那么,要将它们全部包装起来,这些后期静态绑定的使用(以及类似的)是否过度杀伤?是否有明显的性能影响?此外,频繁使用后期绑定是否会降低操作码缓存的整体性能提升?
我和我正在写的应用程序的这个人有同样的问题.问题是静态属性不是在子类中继承的,因此如果我在主类中使用static ::关键字,它也会在我的主类中设置变量.
如果我重新声明我的子类中的静态变量,它可以工作,但我希望有大量的静态属性和子类,并希望避免代码重复.我链接的页面上排名靠前的响应有一些指向"解决方法"的链接,但它似乎有404个.任何人都可以借给我一些帮助,或者让我指出所说的解决方法吗?
看看这个例子,注意输出指示.
<?php
class Mommy
{
protected static $_data = "Mommy Data";
public static function init( $data )
{
static::$_data = $data;
}
public static function showData()
{
echo static::$_data . "<br>";
}
}
class Brother extends Mommy
{
}
class Sister extends Mommy
{
}
Brother::init( "Brother Data" );
Sister::init( "Sister Data" );
Brother::showData(); // Outputs: Sister Data
Sister::showData(); // Outputs: Sister Data
?>
Run Code Online (Sandbox Code Playgroud)
我的理解是使用static关键字将引用子类,但显然它只是在子类中缺少父类时神奇地应用于父类.(这对PHP来说是一种危险的行为,更多内容将在下面解释.)
我有以下两点要记住我为什么要这样做:
但是,如果我们想要在运行时覆盖属性(通过init方法),它将为父类重写它!从那时起,早期初始化的子课程(如兄弟的情况)意外地改变了你.
显然,这是子类没有自己的静态属性副本的结果,只要它没有在子类内部显式定义 - 而不是抛出错误,它会切换静态行为以访问父类.因此,是否存在某种方式,父类可以动态创建属于子类的属性,而不会出现在子类定义中?这样子类可以有自己的静态属性副本,静态关键字可以正确引用它,并且可以编写它以考虑父属性默认值.
还是有其他解决方案,好的,坏的还是丑的?
如何从父静态函数调用子函数?
在php5.3中,有一个内置方法get_called_class(),用于从父类调用子方法.但是我的服务器运行的是php 5.1.
有什么办法可以做到这一点吗?
我想从静态函数中调用它.所以我不能用"$ this"
所以我应该使用"自我"关键字.
下面的示例我的父类是"Test123",来自父类的静态函数"myfunc"我试图像这样调用子类的函数"self :: test();"
abstract class Test123
{
function __construct()
{
// some code here
}
public static function myfunc()
{
self::test();
}
abstract function test();
}
class Test123456 extends Test123
{
function __construct()
{
parent::__construct();
}
function test()
{
echo "So you managed to call me !!";
}
}
$fish = new Test123456();
$fish->test();
$fish->myfunc();
Run Code Online (Sandbox Code Playgroud) 让我们从一些代码开始:
class Super {
protected static $color;
public static function setColor($color){
self::$color = $color;
}
public static function getColor() {
return self::$color;
}
}
class ChildA extends Super { }
class ChildB extends Super { }
ChildA::setColor('red');
ChildB::setColor('green');
echo ChildA::getColor();
echo ChildB::getColor();
Run Code Online (Sandbox Code Playgroud)
现在,PHP 5.3中使用static关键字的后期静态绑定在静态方法中运行得很好,所以我认为它会对静态变量做同样的魔术.好吧,似乎没有.上面的示例不打印出"红色",然后打印出"绿色",正如我的预期,但"绿色"和"绿色".为什么当它适用于方法时,它是否适用于变量?有没有其他方法可以达到我预期的效果?
父类中的代码:
foreach(static::$_aReadOnlyDatabaseTables AS $TableName => $aColumns){
// Do something
}
Run Code Online (Sandbox Code Playgroud)
此工程时,$ _aReadOnlyDatabaseTables在子类中的定义,但在$ _aReadOnlyDatabaseTables不存在抛出一个错误.我需要先检查这个属性是否存在.
我认为它应该是这样的:
if(property_exists(static,$_aReadOnlyDatabaseTables)){
foreach(static::$_aReadOnlyDatabaseTables AS $TableName => $aColumns){
// Do something
}
}
Run Code Online (Sandbox Code Playgroud)
但这会引发语法错误unexpected ',', expecting T_PAAMAYIM_NEKUDOTAYIM.使用$this代替static也不起作用,它总是评估错误.
这个的正确语法是什么?
php ×10
static ×5
late-binding ×3
oop ×3
inheritance ×2
class ×1
php-5.3 ×1
php-ide ×1
phpdoc ×1
variables ×1