实例与静态方法.静态或动态调用 [英] Instance vs. static method. Calling it statically or dynamically

查看:89
本文介绍了实例与静态方法.静态或动态调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在PHP中有实例方法和静态方法(仅这两种类型)?然后我们可以静态地或非静态地调用这些名称(名称是动态地"吗?)?

In PHP there is instance methods and static methods (just these two types)? Then we can call either of these statically or non-statically (is the name "dynamically"?)?

所以我们可以:

  1. 静态调用实例方法;
  2. 非静态地调用实例方法;
  3. 静态调用静态方法;
  4. 非静态地调用静态方法(全部四个正确吗?)

这四个代码的外观如何?有没有好的网站对此进行解释?我目前正在阅读以下网址:

How would the code for these four look? Are there any good websites explaining this? I am currently reading the following url:

http://php.net/manual/zh-CN/language.oop5 .basic.php

...我不明白这一点:

...and I am not understanding this:

"$$是对调用对象的引用(通常是该方法所属的对象,但如果从辅助对象的上下文中静态调用该方法,则可能是另一个对象)."

"$this is a reference to the calling object (usually the object to which the method belongs, but possibly another object, if the method is called statically from the context of a secondary object)."

代码如何查找从辅助对象静态调用方法?我的意思是,staticall调用与非静态调用相比,这是什么?

How would the code look for calling a method statically from a secondary object? I mean, staticall calling vs. non-statical calling, what this is?

推荐答案

您不应静态调用非静态方法.

You are not supposed to call non static methods statically.

一些例子

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

非静态调用static的想法是允许在非静态方法中使用静态属性.例如:

The idea behind calling static non-statically is that its permissible to use static properties inside non static methods. For example:

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
    }
}

这很好,现在反面是在静态方法内部调用非静态方法.

So this is fine, now the flip side is calling non-static methods inside of a static methods.

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__;
    }
}

需要指出的其他一些事情

A few other things to point out

  • 调用静态$ this不可用时,假定您将在非静态方法中使用$ this,因此静态调用它可能会引起问题.
  • 当调用非静态$ this时,并且进行静态调用没有问题,因此非静态调用静态方法不是问题. IE.自我和静态在上下文中均不可用.
  • 静态属性与该类的所有实例共享
  • 在父级中访问的静态属性不能被子级更改(使用self时)
  • 在父级中访问的静态属性可以由子级更改(使用静态,后期静态绑定时)

现在,如果您想要确切的答案:

Now if you want exact answers:

  1. 静态调用实例方法;
    • 您可以但不应该,因为$ this不存在
  1. Call an instance method statically;
    • you can but shouldn't because $this is not exists
  • 这很正常
  • 这也是正常的
  • 确保静态范围内可用

我们可以使用上面的类通过示例来展示

We can show this by example using the above class

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之类的东西)

Result (PHP5 something)

<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 />

现在我们在pr PHP7中没有出现致命错误(某物),乍看之下这似乎没问题.就像它的说法一样,以这种方式运行是很好的.但是,如果您仔细观察Undefined variable: this,实际上这会比致命错误更糟,因为现在您的课程可能会产生意外的结果.

Now we don't get the Fatal error in pr PHP7 (something), and at first glance this may seem ok. Like its saying it's fine to run this way. However if you look closer Undefined variable: this this is actually worse then the Fatal error, because now you class can produce unexpected results.

如果我们称这种情况正常:

If we had called this normal:

(new foo)->biz();

结果

foo::biz //output of __METHOD__
foo Object //output of $this
(
)

因此,我想为您提供一个有关selfstatic的简短示例,这可能会令人困惑.

So I want to give you one quick example on self vs static, it can be really confusing.

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解析类时解析.

When you use static it's called late static binding. What this means is that the static value is bound late. So what doe that really mean? It means the value is resolved at run time, not when the class is parsed by PHP.

  • barfoo的子级.
  • 我们实例化子级foo,我们所有的调用都通过foo.
  • 方法boo仅存在于父级中,即.它不会被子方法覆盖.
  • foo的值为'true'
  • bar的值为'false'
  • bar is a child of foo.
  • We instantiate the child foo, all our calls go through foo.
  • the method boo only exists in the parent, ie. it's not overwritten by a child method.
  • foo's value is 'true'
  • bar's value is 'false'

对于第一个,我们得到foo的值,因为我们使用的是self,所以它只知道自己.

For the fist one, we get the value of foo because we are using self, so it only knows about itself.

对于第二个,我们得到bar的值,因为我们使用的是静态的,它绑定得较晚,并且可以使用在属性$test的声明中设置的子值.因此,即使父母对孩子(通常)一无所知,它也可以使用它的值,因为它在运行时已解决.

For the second one, we get the value of bar because we are using static, it's bound late and can use the child's value which is set in it's declaration of the property $test. So even though the parent doesn't know anything about the child (typical) it can use it's value because it's resolved at run time.

,我们得到bar的值,因为它了解自身,并且该方法是在其自身中定义的. foo对这种方法一无所知,即使它被孩子中的减速所覆盖也是如此.

for the third one, we get the value of bar because it knows about itself, and the method is defined in itself. foo knows nothing about this method even if it did it would be overwritten by the deceleration of it in the child.

对于第四个,我们再次获得bar的值,这是因为即使使用后期静态绑定,我们也会提取相同的数据,而bar的值是因为bar是我们实例化的类,因此在运行时的时间中,在的属性中定义的值就是该值.

for the fourth one, again we get the value of bar this is because even with late static binding we pull the same data, the value of bar because bar is the class we instantiated, so at run time the value defined in's property is the value.

所以在最后2个值是相同的,这是因为self和static解析相同的信息,而不管它们何时被调用.

So in the last 2 the value is the same, it's because self and static resolve the same information regardless of when they are called.

这可能非常令人困惑,因此希望它是有道理的.同样,正如我所展示的,不要害怕制作这样的简单类并测试您获得的值.这就是我学到的.

This can be very confusing so hopefully it makes sense. Also as I have shown don't be afraid to make some simple classes like this and test the values you get. That's how I learned.

您提到使用静态调用被认为是不好的.

You mentioned using static calls was considered bad.

我认为大部分来自依赖性问题.这是类名和代码之间的紧密耦合.使用实例时,将其分配给变量,并在调用new时使用名称1次.调用static时,您每次都使用类名.导致的问题是,如果您决定重命名该类.使用实例调用,您只需要在调用new的地方替换名称,就可以使用static替换所有地方的名称.

I think most of that comes from Dependency issues. This is tight coupling between the name of the class and your code. When using an instance, you assign it to variable and use the name 1 time when calling new. When calling static you use the class name every time. The problem this causes is if you decide to rename the class. With instance calls you only need to replace the name where you call new, with static you have to replace it everywhere.

例如考虑一下.

$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();

现在说您更改班级名称.对于第一个,您必须将其替换在一个位置.对于第二个,您必须在使用它的地方替换它.您可以通过使用字符串变量来解决此问题.

Now say you change the class name. For the first one you have to replace it in one place. For the second one you have to replace it evey where you used it. You can get around this somewhat by using a string variable.

$class = 'foo';
$class::one();
$class::two();
//say you inject this into another class
$class::three();

但是与此同时,您也会遇到很多麻烦,因为大多数IDE都无法解析该类并执行自动补全.

But with this you can get into a lot of trouble too, because most IDE's wont be able to resolve the class and do auto-completion.

如果您确实在其他类的输入上键入提示

Also if you do type hinting on inputs to other classes

 class other{ 
    public method inject(foo $foo){}
 }

这在静态类上效果不佳,因为您当时要传递一个字符串(类名).

This doesn't work very well on static classes, because you are passing in a string then (the class name).

命名空间可能是个问题.使用实例化,您只需要将use语句放入实例化该类的文件中.使用静态方法,则必须将其放置在任何地方,或将其包含在每个调用中.

Namespaces can be an issue. With instantiation, you only need to put the use statement in the file you instantiate the class in. With static, you have to put it everywhere, or include it in every call.

 \mystuff\foo::bar();

 $foo = '\\mystuff\\foo';
 $foo::bar();

我确定还有其他原因,但这是我的主要原因.

I am sure there are other reasons, but these are the main ones for me.

这篇关于实例与静态方法.静态或动态调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆