理解范围解析运算符';PHP语言中的s定义
在php手册中,它们定义了范围解析运算符,如下所示: 范围解析运算符(也称为Paamayim-Nekudotayim)或更简单的术语,即双冒号,是允许访问静态、常量和重写属性或类的方法的标记 我的理解是,因为我们不能用理解范围解析运算符';PHP语言中的s定义,php,inheritance,static,static-methods,scope-resolution-operator,Php,Inheritance,Static,Static Methods,Scope Resolution Operator,在php手册中,它们定义了范围解析运算符,如下所示: 范围解析运算符(也称为Paamayim-Nekudotayim)或更简单的术语,即双冒号,是允许访问静态、常量和重写属性或类的方法的标记 我的理解是,因为我们不能用$this评估静态属性、类常量和静态方法,所以我们需要:。我不明白为什么允许:从类内部评估非静态函数。可以说,子类可能希望使用parent::baseClassMethod()评估父类中定义的方法,但是它可能也想评估父类中定义的属性,但是:无法评估属性。可以说父类的属性是继承的,所
$this
评估静态属性、类常量和静态方法,所以我们需要:
。我不明白为什么允许:
从类内部评估非静态函数。可以说,子类可能希望使用parent::baseClassMethod()
评估父类中定义的方法,但是它可能也想评估父类中定义的属性,但是:
无法评估属性。可以说父类的属性是继承的,所以我们可以简单地用$this->prop
来评估它们,但方法也是如此。只有当方法在子类中被重写时,我们才对它们使用::
。类似地,我们需要:
来评估子类中重写的属性。与php手动定义相反,如果尝试使用::
评估重写的属性,则会抛出错误
为了说明我的观点,我有以下PHP代码示例:
error_reporting(E_ALL);
class myClass {
private $prop = 786;
public $prop2 = 123;
public function changeType($var, $type){
settype($var, $type);
echo "function assessed through self";
}
public function display_prop(){
self::changeType(1, "string"); //why does this not throw error for non static function?
var_dump(self::$prop); //throws error; can't assess properties with self as expected.
}
}
class childCLass extends myClass {
public $prop2 = "new"; //overriden property.
public function display_prop(){ //overriden method.
echo "I do different things from the base class". "</br>";
}
public function dsiplay_overriden(){
echo parent::$prop2; //Why can't assess overriden properties, as suggested in the definition?
}
}
$obj = new myClass;
$obj->display_prop();
$obj2 = new childCLass;
$obj2->display_prop();
$obj2->dsiplay_overriden();
childClass::display_prop(); //This throws error as expected because non-static method.
错误报告(E_ALL);
类myClass{
私人$prop=786;
公共支出$prop2=123;
公共函数changeType($var,$type){
settype($var$type);
echo“通过自我评估功能”;
}
公共功能显示_prop(){
self::changeType(1,“string”);//为什么这不会引发非静态函数的错误?
var_dump(self::$prop);//抛出错误;无法按预期使用self评估属性。
}
}
类childCLass扩展了myClass{
public$prop2=“new”//重写的属性。
公共函数display_prop(){//重写的方法。
echo“我做的事情与基类不同”。;
}
公共函数dsiplay_重写(){
echo parent::$prop2;//为什么不能按照定义中的建议评估重写的属性?
}
}
$obj=新的myClass;
$obj->display_prop();
$obj2=新的子类;
$obj2->display_prop();
$obj2->dsiplay_overrided();
childClass::display_prop()//这会引发预期的错误,因为该方法是非静态的。
总而言之,我主要有两个具体问题:
:
访问覆盖的属性:
访问类中的非静态函数注:关于stackoverflow,有人问过A。没有令人满意的答案存在,而且我正在寻找一个概念性的和有见地的答案,这在programmers.stackexchange更合适 我试试看:) 方法和静态属性在内存中只存在一次,类实例(对象)的非静态属性在每个实例中都存在,例如,在内存中有自己的空间
范围解析运算符(也称为Paamayim-Nekudotayim)或更简单的术语,即双冒号,是允许访问类的静态、常量和重写属性或方法的标记。
事实上,它解析作用域,例如,它确定是否必须访问静态(共享)或本地内存$this
只能访问本地内存,它代表“对当前实例的引用”,在非静态类方法中自动可用,但在静态方法中不可用!历史上,它来自C++(关键字“这个”),其中类方法在所有类方法的函数指针映射中组织,即所谓的V表。所有非静态类方法都会收到一个名为“this”的附加(不可见)最后一个参数,对非静态方法的调用会在运行时解析(与编译时解析的静态方法相反)
现在,当您创建一个类的实例时,比如$obj=newfoo()代码>将发生两件事-为对象分配内存,并调用类的构造函数。构造函数不能声明为静态的,因为它们负责正确初始化内存。作为非静态方法,他们将自动接收$this
因此,当调用非静态方法时,如$obj->method()
,运行时环境将识别,$obj
是类实例。它检查类的v-table以找到方法(它只是一个常规函数,但带有额外的参数$this),并调用它,将$obj
作为$this
传递,伪代码$vtable['Foo']['method']($obj)
。在类方法中,您可以访问$this
最后,静态调用非静态方法,分别以非静态方式调用静态方法:
事实上,如果你牢记这一点,你可以两者兼得
非静态方法,使用Foo::bar()调用代码>:$此
将为空
静态方法,使用调用<
class A {
public $x = 'a_x';
protected $y = 'a_y';
private $z = 'a_z';
}
class B extends A {
public $x = 'b_x';
protected $y = 'b_y';
private $z = 'b_z';
public static function foo() {
echo 'foo' . PHP_EOL;
}
public function bar() {
echo 'bar' . PHP_EOL;
}
}
$a = new A();
$b = new B();
var_dump($a, $b);
$b->foo();
B::bar();
object(A)#1 (3) {
["x"]=>
string(3) "a_x"
["y":protected]=>
string(3) "a_y"
["z":"A":private]=>
string(3) "a_z"
}
object(B)#2 (4) {
["x"]=>
string(3) "b_x"
["y":protected]=>
string(3) "b_y"
["z":"B":private]=>
string(3) "b_z"
["z":"A":private]=>
string(3) "a_z"
}
foo
bar