在PHP中有实例方法和静态方法(只是这两种类型)?然后我们可以静态或非静态地调用其中任何一个(名称"动态"?)?
所以我们可以:
这四个代码看起来怎么样?有没有好的网站解释这个?我目前正在阅读以下网址:
http://php.net/manual/en/language.oop5.basic.php
......我不理解这个:
" $这是对调用对象的引用(通常是方法所属的对象,但如果从辅助对象的上下文中静态调用该方法,则可能是另一个对象)。"
代码如何从次要对象静态调用方法?我的意思是,staticall调用与非静态调用,这是什么?
答案 0 :(得分:1)
您不应该静态调用非静态方法。
一些例子
class foo{
public static function bar(){
echo __METHOD__;
}
public function biz(){
echo __METHOD__;
}
}
测试
//instance call
(new foo)->biz(); //echos foo::biz (don't worry about the :: here, its part of __METHOD__)
//static call, statically
foo::bar() // echos foo::bar
//call non-static statically
foo::biz() //in PHP7.1
<b>Deprecated</b>: Non-static method foo::biz() should not be called statically in <b>[...][...]</b> on line <b>18</b><br />
//call static non-statically
(new foo)->bar(); // echos foo::bar
静态非静态调用背后的想法是允许在非静态方法中使用静态属性。例如:
class foo{
protected static $boo = "hello";
public static function bar(){
echo __METHOD__;
}
public function biz(){
echo __METHOD__;
echo self::$boo;
echo static::$boo; //late static binding
}
}
所以这很好,现在另一方面是在静态方法中调用非静态方法。
class foo{
protected $boo = "hello";
public static function bar(){
echo __METHOD__;
$this->boo; // this is a no no, because no instance exists and therefor $this does not work
}
public function biz(){
echo __METHOD__;
}
}
要指出的其他一些事项
现在,如果你想要确切答案:
我们可以使用上面的类
来举例说明class foo{
public static function bar(){
echo __METHOD__;
}
public function biz(){
echo __METHOD__;
print_r($this);
}
}
//call non-static statically
foo::biz();
结果(PHP7 +)
<br />
<b>Deprecated</b>: Non-static method foo::biz() should not be called statically in <b>[...][...]</b> on line <b>15</b><br />
foo::biz //output of __METHOD__
<br />
<b>Fatal error</b>: Uncaught Error: Using $this when not in object context in [...][...]:11
Stack trace:
#0 [...][...](15): foo::biz()
#1 {main}
thrown in <b>[...][...]</b> on line <b>11</b><br />
如您所见,我们在尝试访问$this
结果(PHP5的东西)
<br />
<b>Strict Standards</b>: Non-static method foo::biz() should not be called statically in <b>[...][...]</b> on line <b>16</b><br />
foo::biz<br />
<b>Notice</b>: Undefined variable: this in <b>[...][...]</b> on line <b>11</b><br />
现在我们没有在PHP7(某事)中得到致命错误,乍一看这似乎没问题。就像它说这样运行一样好。但是,如果你仔细观察Undefined variable: this
,这实际上比致命错误更糟,因为现在你的班级会产生意想不到的结果。
如果我们称之为正常:
(new foo)->biz();
结果
foo::biz //output of __METHOD__
foo Object //output of $this
(
)
所以我想在self
vs static
上给你一个简单的例子,这可能会令人困惑。
class foo{
protected static $test = 'true';
public function boo(){
echo self::$test."\n";
echo static::$test."\n";
}
}
class bar extends foo{
protected static $test = 'false';
public function biz(){
echo self::$test."\n";
echo static::$test."\n";
}
}
$B = new bar;
$B->boo();
echo "--------------\n";
$B->biz();
结果
-------------- defined in parent ----
true //call boo() self
false //call boo() static
-------------- defined in child ----
false //call biz() self
false //call biz() static
当您使用static
时,它被称为后期静态绑定。这意味着静态值是迟到的。那真正意味着什么呢?这意味着该值在运行时解析,而不是在PHP解析类时解析。
bar
是foo
的孩子。 foo
,我们所有的电话都通过了foo
。 boo
仅存在于父级中,即。它没有被儿童方法覆盖。对于第一个,我们得到foo
的值,因为我们使用的是自我,所以它只知道自己。
对于第二个,我们得到bar
的值,因为我们使用静态,它的后期绑定并且可以使用在其中设置的子值。声明属性$test
。因此,尽管父母对孩子一无所知(典型),但它可以使用它的价值,因为它在运行时得到了解决。
对于第三个,我们得到bar
的值,因为它知道自己,并且该方法本身已定义。 foo
对这种方法一无所知,即使它确实会被孩子的减速所覆盖。
对于第四个,我们再次获得bar
的值这是因为即使使用后期静态绑定,我们也会提取相同的数据,bar
的值,因为bar
是类我们实例化了,所以在运行时,在属性中定义的值是值。
因此,在最后2中,值是相同的,因为自身和静态解析相同的信息,无论它们何时被调用。
这可能非常令人困惑,所以希望它有意义。另外,正如我已经表明的那样,不要害怕做一些像这样的简单课程并测试你得到的价值观。这就是我学习的方式。
你提到使用静态调用被认为是坏的。
我认为大部分都来自依赖性问题。这是类的名称和代码之间的紧密耦合。使用实例时,将其分配给变量,并在调用new时使用名称1次。调用static时,每次都使用类名。这导致的问题是您决定重命名该类。对于实例调用,您只需要替换调用new的名称,使用static,您必须在任何地方替换它。
例如考虑这一点。
$foo = new foo;
$foo->one();
$foo->two();
//say you inject this into another class
$foo->three();
并将其与此进行比较。
foo::one();
foo::two();
//say you inject this into another class
foo::three();
现在说你改变了班级名称。对于第一个,你必须在一个地方更换它。对于第二个,您必须将它替换为您使用它的地方。你可以通过使用字符串变量来解决这个问题。
$class = 'foo';
$class::one();
$class::two();
//say you inject this into another class
$class::three();
但是有了这个,你也会遇到很多麻烦,因为大多数IDE都无法解决这个问题而且会自动完成。
此外,如果您在其他类的输入上键入提示
class other{
public method inject(foo $foo){}
}
这对静态类没有用,因为你传入一个字符串然后(类名)。
命名空间可能是个问题。通过实例化,您只需要将use语句放在您实例化类的文件中。对于静态,您必须将它放在任何地方,或者在每次调用中包含它。
\mystuff\foo::bar();
$foo = '\\mystuff\\foo';
$foo::bar();
我确信还有其他原因,但这些是我的主要原因。
答案 1 :(得分:0)
让我们看看以下代码:
@objc
它会显示<?php
class A
{
public $property = "property A";
public function testA()
{
echo "class A ";
echo $this->property;
}
}
class B
{
public $property = "property B";
public function testB()
{
A::testA();
}
}
$b = new B;
$b->testB();
您正在使用class A property B
在B
课程中A
访问某个媒体资源。
这不适用于PHP 7+,您将在PHP 5.6上收到以下警告:
$this
它“有效”,但你不应该从静态上下文中调用非静态方法。