php 什么时候在 $this 上使用 self ?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/151969/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 21:41:49  来源:igfitidea点击:

When to use self over $this?

phpclassoopscope

提问by Casey Watson

In PHP 5, what is the difference between using selfand $this?

在 PHP 5 中,使用self和 有$this什么区别?

When is each appropriate?

什么时候合适?

采纳答案by John Millikin

Short Answer

简答

Use $thisto refer to the current object. Use selfto refer to the current class. In other words, use $this->memberfor non-static members, use self::$memberfor static members.

使用$this来指代当前对象。用self指当前类。换句话说, $this->member用于非静态成员,self::$member用于静态成员。

Full Answer

完整答案

Here is an example of correctusage of $thisand selffor non-static and static member variables:

以下是非静态和静态成员变量的正确使用$this和使用示例self

<?php
class X {
    private $non_static_member = 1;
    private static $static_member = 2;

    function __construct() {
        echo $this->non_static_member . ' '
           . self::$static_member;
    }
}

new X();
?>

Here is an example of incorrectusage of $thisand selffor non-static and static member variables:

这里是一个例子不正确的使用$thisself用于非静态和静态成员变量:

<?php
class X {
    private $non_static_member = 1;
    private static $static_member = 2;

    function __construct() {
        echo self::$non_static_member . ' '
           . $this->static_member;
    }
}

new X();
?>

Here is an example of polymorphismwith $thisfor member functions:

下面是一个使用for 成员函数的多态示例$this

<?php
class X {
    function foo() {
        echo 'X::foo()';
    }

    function bar() {
        $this->foo();
    }
}

class Y extends X {
    function foo() {
        echo 'Y::foo()';
    }
}

$x = new Y();
$x->bar();
?>

Here is an example of suppressing polymorphic behaviourby using selffor member functions:

以下是使用for 成员函数抑制多态行为的示例self

<?php
class X {
    function foo() {
        echo 'X::foo()';
    }

    function bar() {
        self::foo();
    }
}

class Y extends X {
    function foo() {
        echo 'Y::foo()';
    }
}

$x = new Y();
$x->bar();
?>

The idea is that $this->foo()calls the foo()member function of whatever is the exact type of the current object. If the object is of type X, it thus calls X::foo(). If the object is of type Y, it calls Y::foo(). But with self::foo(), X::foo()is always called.

这个想法是$this->foo()调用foo()当前对象的确切类型的成员函数。如果对象是type X,则它因此调用X::foo()。如果对象是type Y,则调用Y::foo()。但是对于 self::foo(),X::foo()总是被调用。

From http://www.phpbuilder.com/board/showthread.php?t=10354489:

http://www.phpbuilder.com/board/showthread.php?t=10354489

By http://board.phpbuilder.com/member.php?145249-laserlight

通过http://board.phpbuilder.com/member.php?145249-laserlight

回答by nbeagle

The keyword self does NOTrefer merely to the 'current class', at least not in a way that restricts you to static members. Within the context of a non-static member, selfalso provides a way of bypassing the vtable (see wiki on vtable) for the current object. Just as you can use parent::methodName()to call the parents version of a function, so you can call self::methodName()to call the current classes implementation of a method.

关键字自不只是指“当前类的,至少不会在某种程度上,限制你的静态成员。在非静态成员的上下文中,self还提供了一种绕过当前对象的 vtable(请参阅 vtable 上的 wiki)的方法。正如您可以parent::methodName()用来调用函数的父版本一样,您也可以调用self::methodName()来调用方法的当前类实现。

class Person {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }

    public function getTitle() {
        return $this->getName()." the person";
    }

    public function sayHello() {
        echo "Hello, I'm ".$this->getTitle()."<br/>";
    }

    public function sayGoodbye() {
        echo "Goodbye from ".self::getTitle()."<br/>";
    }
}

class Geek extends Person {
    public function __construct($name) {
        parent::__construct($name);
    }

    public function getTitle() {
        return $this->getName()." the geek";
    }
}

$geekObj = new Geek("Ludwig");
$geekObj->sayHello();
$geekObj->sayGoodbye();

This will output:

这将输出:

Hello, I'm Ludwig the geek
Goodbye from Ludwig the person

你好,我是极客
路德维希 再见路德维希这个人

sayHello()uses the $thispointer, so the vtable is invoked to call Geek::getTitle(). sayGoodbye()uses self::getTitle(), so the vtable is not used, and Person::getTitle()is called. In both cases, we are dealing with the method of an instantiated object, and have access to the $thispointer within the called functions.

sayHello()使用$this指针,因此调用 vtable 来调用Geek::getTitle(). sayGoodbye()uses self::getTitle(),所以 vtable 没有被使用,Person::getTitle()而是被调用。在这两种情况下,我们都在处理实例化对象的方法,并且可以访问$this被调用函数中的指针。

回答by Sqoo

DO NOT USE self::, use static::

不要使用self::,使用static::

There is another aspect of self:: that is worth mentioning. Annoyingly self::refers to the scope at the point of definition not at the point of execution. Consider this simple class with two methods:

self:: 还有另一个方面值得一提。Annoyinglyself::指的是定义点而不是执行点的范围。考虑这个带有两种方法的简单类:

class Person
{

    public static function status()
    {
        self::getStatus();
    }

    protected static function getStatus()
    {
        echo "Person is alive";
    }

}

If we call Person::status()we will see "Person is alive" . Now consider what happens when we make a class that inherits from this:

如果我们打电话,Person::status()我们会看到“人还活着”。现在考虑当我们创建一个继承自 this 的类时会发生什么:

class Deceased extends Person
{

    protected static function getStatus()
    {
        echo "Person is deceased";
    }

}

Calling Deceased::status()we would expect to see "Person is deceased" however what we see is "Person is alive" as the scope contains the original method definition when call to self::getStatus()was defined.

调用Deceased::status()我们希望看到“Person is deceased”,但是我们看到的是“Person is alive”,因为范围包含定义调用时的原始方法定义self::getStatus()

PHP 5.3 has a solution. the static::resolution operator implements "late static binding" which is a fancy way of saying that it's bound to the scope of the class called. Change the line in status()to static::getStatus()and the results are what you would expect. In older versions of PHP you will have to find a kludge to do this.

PHP 5.3 有一个解决方案。该static::解决运营商实施“后期静态绑定”,这是说,它必然要调用的类范围的一个奇特的方式。将行更改status()static::getStatus(),结果就是您所期望的。在旧版本的 PHP 中,您必须找到一个工具才能做到这一点。

See PHP Documentation

请参阅PHP 文档

So to answer the question not as asked ...

所以要回答这个问题而不是问...

$this->refers to the current object (an instance of a class), whereas static::refers to a class

$this->指的是当前对象(类的实例),而static::指的是类

回答by ircmaxell

To really understand what we're talking about when we talk about selfversus $this, we need to actually dig into what's going on at a conceptual and a practical level. I don't really feel any of the answers do this appropriately, so here's my attempt.

当我们谈论selfvs 时$this,要真正理解我们在谈论什么,我们需要在概念和实践层面深入研究正在发生的事情。我真的不觉得任何答案都正确地做到了这一点,所以这是我的尝试。

Let's start off by talking about what a classand an objectis.

让我们首先讨论什么是对象

Classes And Objects, Conceptually

概念上的类和对象

So, what isa class? A lot of people define it as a blueprintor a templatefor an object. In fact, you can read more About Classes In PHP Here. And to some extent that's what it really is. Let's look at a class:

那么,什么?很多人将其定义为对象的蓝图模板。事实上,您可以在此处阅读更多关于 PHP 中的类的信息。在某种程度上,这就是它的真正含义。我们来看一个类:

class Person {
    public $name = 'my name';
    public function sayHello() {
        echo "Hello";
    }
}

As you can tell, there is a property on that class called $nameand a method (function) called sayHello().

如您所知,该类上有一个名为 的属性$name和一个名为的方法(函数)sayHello()

It's veryimportant to note that the classis a static structure. Which means that the class Person, once defined, is always the same everywhere you look at it.

这是非常值得注意的是,重要的是静态结构。这意味着 class Person,一旦定义,无论你在哪里看到它都是一样的。

An object on the other hand is what's called an instanceof a Class. What that means is that we take the "blueprint" of the class, and use it to make a dynamic copy. This copy is now specifically tied to the variable it's stored in. Therefore, any changes to an instanceis local to that instance.

另一方面,对象是所谓的类的实例。这意味着我们获取类的“蓝图”,并使用它来制作动态副本。这个副本现在特别绑定到它存储的变量。因此,对实例的任何更改都是该实例的本地更改。

$bob = new Person;
$adam = new Person;
$bob->name = 'Bob';
echo $adam->name; // "my name"

We create new instancesof a class using the newoperator.

我们使用运算符创建类的新实例new

Therefore, we say that a Class is a global structure, and an Object is a local structure. Don't worry about that funny ->syntax, we're going to go into that in a little bit.

因此,我们说Class是全局结构,Object是局部结构。不要担心那个有趣的->语法,我们稍后会深入探讨。

One other thing we should talk about, is that we can checkif an instance is an instanceofa particular class: $bob instanceof Personwhich returns a boolean if the $bobinstance was made using the Personclass, ora child of Person.

我们应该讨论的另一件事是,我们可以检查一个实例是否是instanceof一个特定的类:$bob instanceof Person如果$bob实例是使用Person该类创建的,或者Person.

Defining State

定义状态

So let's dig a bit into what a class actually contains. There are 5 types of "things" that a class contains:

因此,让我们深入研究一个类实际包含的内容。一个类包含 5 种类型的“事物”:

  1. Properties- Think of these as variables that each instance will contain.

    class Foo {
        public $bar = 1;
    }
    
  2. Static Properties- Think of these as variables that are shared at the class level. Meaning that they are never copied by each instance.

    class Foo {
        public static $bar = 1;
    }
    
  3. Methods- These are functions which each instance will contain (and operate on instances).

    class Foo {
        public function bar() {}
    }
    
  4. Static Methods- These are functions which are shared across the entire class. They do notoperate on instances, but instead on the static properties only.

    class Foo {
        public static function bar() {}
    }
    
  5. Constants- Class resolved constants. Not going any deeper here, but adding for completeness:

    class Foo {
        const BAR = 1;
    }
    
  1. 属性- 将这些视为每个实例将包含的变量。

    class Foo {
        public $bar = 1;
    }
    
  2. 静态属性- 将它们视为在类级别共享的变量。这意味着它们永远不会被每个实例复制。

    class Foo {
        public static $bar = 1;
    }
    
  3. 方法- 这些是每个实例将包含(并对实例进行操作)的函数。

    class Foo {
        public function bar() {}
    }
    
  4. 静态方法- 这些是在整个类中共享的函数。它们不对实例进行操作,而是仅对静态属性进行操作。

    class Foo {
        public static function bar() {}
    }
    
  5. 常量- 类解析的常量。这里不会更深入,但为了完整性而添加:

    class Foo {
        const BAR = 1;
    }
    

So basically, we're storing information on the class and object container using "hints" about staticwhich identify whether the information is shared (and hence static) or not (and hence dynamic).

所以基本上,我们使用关于静态的“提示”来存储关于类和对象容器的信息,这些“提示”标识信息是共享的(因此是静态的)还是不共享的(因此是动态的)。

State and Methods

状态和方法

Inside of a method, an object's instance is represented by the $thisvariable. The current state of that object is there, and mutating (changing) any property will result in a change to that instance (but not others).

在方法内部,对象的实例由$this变量表示。该对象的当前状态就在那里,改变(改变)任何属性都将导致该实例(而不是其他)发生变化。

If a method is called statically, the $thisvariable is not defined. This is because there's no instance associated with a static call.

如果静态调用方法,则未定义$this变量。这是因为没有与静态调用关联的实例。

The interesting thing here is how static calls are made. So let's talk about how we access the state:

这里有趣的是静态调用是如何进行的。那么让我们来谈谈我们如何访问状态:

Accessing State

访问状态

So now that we have stored that state, we need to access it. This can get a bit tricky (or waymore than a bit), so let's split this into two viewpoints: from outside of an instance/class (say from a normal function call, or from the global scope), and inside of an instance/class (from within a method on the object).

所以现在我们已经存储了那个状态,我们需要访问它。这能有点棘手(或方式多一点),所以让我们拆到这两种观点:从一个实例/类以外的(说从一个普通的函数调用,或从全球范围),以及一个实例内部/class(来自对象的方法内)。

From Outside Of An Instance/Class

从实例/类之外

From the outside of an instance/class, our rules are quite simple and predictable. We have two operators, and each tells us immediately if we're dealing with an instance or a class static:

从实例/类的外部来看,我们的规则非常简单且可预测。我们有两个运算符,每个运算符都会立即告诉我们是在处理实例还是静态类:

  • ->- object-operator- This is always used when we're accessing an instance.

    $bob = new Person;
    echo $bob->name;
    

    It's important to note that calling Person->foodoes not make sense (since Personis a class, not an instance). Therefore, that is a parse error.

  • ::- scope-resolution-operator- This is always used to access a Class static property or method.

    echo Foo::bar()
    

    Additionally, we can call a static method on an object in the same way:

    echo $foo::bar()
    

    It's extremelyimportant to note that when we do this from outside, the object's instance is hidden from the bar()method. Meaning that it's the exact same as running:

    $class = get_class($foo);
    $class::bar();
    
  • ->- object-operator- 当我们访问一个实例时总是使用它。

    $bob = new Person;
    echo $bob->name;
    

    重要的是要注意调用Person->foo没有意义(因为Person是一个类,而不是一个实例)。因此,这是一个解析错误。

  • ::-范围解析运算符- 这总是用于访问类静态属性或方法。

    echo Foo::bar()
    

    此外,我们可以以相同的方式调用对象的静态方法:

    echo $foo::bar()
    

    这是非常需要注意的是,我们这样做时,重要的来自外部的对象的实例从隐藏的bar()方法。这意味着它与运行完全相同:

    $class = get_class($foo);
    $class::bar();
    

Therefore, $thisis not defined in the static call.

因此,$this在静态调用中没有定义。

From Inside Of An Instance/Class

从实例/类内部

Things change a bit here. The same operators are used, but their meaning becomes significantly blurred.

事情在这里发生了一些变化。使用了相同的运算符,但它们的含义变得明显模糊。

The object-operator->is still used to make calls to the object's instance state.

对象的操作->仍然是用来对对象的实例状态的呼叫。

class Foo {
    public $a = 1;
    public function bar() {
        return $this->a;
    }
}

Calling the bar()method on $foo(an instance of Foo) using the object-operator: $foo->bar()will result in the instance's version of $a.

使用 object-operator:调用(的实例)bar()上的方法将导致实例的版本。$fooFoo$foo->bar()$a

So that's how we expect.

这就是我们所期望的。

The meaning of the ::operator though changes. It depends on the context of the call to the current function:

::运算符的含义虽然发生了变化。这取决于调用当前函数的上下文:

  • Within a static context

    Within a static context, any calls made using ::will also be static. Let's look at an example:

    class Foo {
        public function bar() {
            return Foo::baz();
        }
        public function baz() {
            return isset($this);
        }
    }
    

    Calling Foo::bar()will call the baz()method statically, and hence $thiswill notbe populated. It's worth noting that in recent versions of PHP (5.3+) this will trigger an E_STRICTerror, because we're calling non-static methods statically.

  • Within an instance context

    Within an instance context on the other hand, calls made using ::depend on the receiver of the call (the method we're calling). If the method is defined as static, then it will use a static call. If it's not, it will forward the instance information.

    So, looking at the above code, calling $foo->bar()will return true, since the "static" call happens inside of an instance context.

  • 在静态上下文中

    在静态上下文中,使用 using 进行的任何调用::也将是静态的。让我们看一个例子:

    class Foo {
        public function bar() {
            return Foo::baz();
        }
        public function baz() {
            return isset($this);
        }
    }
    

    调用Foo::bar()将调用baz()静态方法,因此$this不会被填充。值得注意的是,在最新版本的 PHP (5.3+) 中,这将触发E_STRICT错误,因为我们静态调用非静态方法。

  • 在实例上下文中

    另一方面,在实例上下文中,使用 using::进行的调用取决于调用的接收者(我们正在调用的方法)。如果该方法定义为static,则它将使用静态调用。如果不是,它将转发实例信息。

    因此,查看上面的代码,调用$foo->bar()将返回true,因为“静态”调用发生在实例上下文内。

Make sense? Didn't think so. It's confusing.

有道理?没想到 这很混乱。

Short-Cut Keywords

快捷关键词

Because tying everything together using class names is rather dirty, PHP provides 3 basic "shortcut" keywords to make scope resolving easier.

因为使用类名将所有内容捆绑在一起相当脏,所以 PHP 提供了 3 个基本的“快捷方式”关键字来使范围解析更容易。

  • self- This refers to the current class name. So self::baz()is the same as Foo::baz()within the Fooclass (any method on it).

  • parent- This refers to the parent of the current class.

  • static- This refers to the called class. Thanks to inheritance, child classes can override methods and static properties. So calling them using staticinstead of a class name allows us to resolve where the call came from, rather than the current level.

  • self- 这是指当前的类名。So与类内self::baz()相同(任何方法都可以)。Foo::baz()Foo

  • parent- 这是指当前班级的父级。

  • static- 这是指被调用的类。由于继承,子类可以覆盖方法和静态属性。因此,使用static而不是类名调用它们允许我们解析调用来自何处,而不是当前级别。

Examples

例子

The easiest way to understand this is to start looking at some examples. Let's pick a class:

理解这一点的最简单方法是开始查看一些示例。让我们选择一个类:

class Person {
    public static $number = 0;
    public $id = 0;
    public function __construct() {
        self::$number++;
        $this->id = self::$number;
    }
    public $name = "";
    public function getName() {
        return $this->name;
    }
    public function getId() {
        return $this->id;
    }
}

class Child extends Person {
    public $age = 0;
    public function __construct($age) {
        $this->age = $age;
        parent::__construct();
    }
    public function getName() {
        return 'child: ' . parent::getName();
    }
}

Now, we're also looking at inheritance here. Ignore for a moment that this is a bad object model, but let's look at what happens when we play with this:

现在,我们也在这里研究继承。暂时忽略这是一个糟糕的对象模型,但让我们看看当我们玩这个时会发生什么:

$bob = new Person;
$bob->name = "Bob";
$adam = new Person;
$adam->name = "Adam";
$billy = new Child;
$billy->name = "Billy";
var_dump($bob->getId()); // 1
var_dump($adam->getId()); // 2
var_dump($billy->getId()); // 3

So the ID counter is shared across both instances and the children (because we're using selfto access it. If we used static, we could override it in a child class).

因此 ID 计数器在实例和子类之间共享(因为我们正在使用self它来访问它。如果我们使用static,我们可以在子类中覆盖它)。

var_dump($bob->getName()); // Bob
var_dump($adam->getName()); // Adam
var_dump($billy->getName()); // child: Billy

Note that we're executing the Person::getName()instancemethod every time. But we're using the parent::getName()to do it in one of the cases (the child case). This is what makes this approach powerful.

请注意,我们每次都在执行Person::getName()实例方法。但是我们parent::getName()在其中一种情况(子情况)中使用来做到这一点。这就是使这种方法强大的原因。

Word Of Caution #1

注意事项 #1

Note that the calling context is what determines if an instance is used. Therefore:

请注意,调用上下文决定是否使用实例。所以:

class Foo {
    public function isFoo() {
        return $this instanceof Foo;
    }
}

Is not alwaystrue.

并不总是如此。

class Bar {
    public function doSomething() {
        return Foo::isFoo();
    }
}
$b = new Bar;
var_dump($b->doSomething()); // bool(false)

Now it is reallyweird here. We're calling a different class, but the $thisthat gets passed to the Foo::isFoo()method is the instance of $bar.

现在这里真的很奇怪。我们正在调用一个不同的类,但$this传递给Foo::isFoo()方法的是 的实例$bar

This can cause all sorts of bugs and conceptual WTF-ery. So I'd highly suggest avoiding the ::operator from within instance methods on anything except those three virtual "short-cut" keywords (static, self, and parent).

这可能会导致各种错误和概念性的 WTF-ery。所以我强烈建议避免了::运营商从实例方法中的任何东西,除了这三个虚拟的“捷径”关键字(staticself,和parent)。

Word Of Caution #2

注意事项 #2

Note that static methods and properties are shared by everyone. That makes them basically global variables. With all the same problems that come with globals. So I would be really hesitant to store information in static methods/properties unless you're comfortable with it being truly global.

请注意,静态方法和属性是所有人共享的。这使得它们基本上是全局变量。具有与全局变量相同的所有问题。因此,除非您对真正的全局性感到满意,否则我真的很犹豫将信息存储在静态方法/属性中。

Word Of Caution #3

注意事项 #3

In general you'll want to use what's known as Late-Static-Binding by using staticinstead of self. But note that they are not the same thing, so saying "always use staticinstead of selfis really short-sighted. Instead, stop and think about the call you want to make and think if you want child classes to be able to override that static resolvedcall.

通常,您会希望通过使用static代替来使用所谓的后期静态绑定self。但请注意,它们不是一回事,所以说“总是使用static代替而不是self真的短视。相反,停下来想想你想打的电话,想想你是否希望子类能够覆盖静态解析称呼。

TL/DR

TL/DR

Too bad, go back and read it. It may be too long, but it's that long because this is a complex topic

太可惜了,回去读吧。可能太长了,但就是这么长,因为这是一个复杂的话题

TL/DR #2

TL/DR #2

Ok, fine. In short, selfis used to reference the current class namewithin a class, where as $thisrefers to the current object instance. Note that selfis a copy/paste short-cut. You can safely replace it with your class name, and it'll work fine. But $thisis a dynamic variable that can't be determined ahead of time (and may not even be your class).

好的。简而言之,self用于引用的当前类名,其中 as$this指的是当前对象实例。请注意,这self是复制/粘贴快捷方式。你可以安全地用你的类名替换它,它会正常工作。但是$this是一个无法提前确定的动态变量(甚至可能不是您的班级)。

TL/DR #3

TL/DR #3

If the object-operator is used (->), then you alwaysknow you're dealing with an instance. If the scope-resolution-operator is used (::), you need more information about the context (are we in an object-context already? Are we outside of an object? etc).

如果使用了对象运算符 ( ->),那么您总是知道您正在处理一个实例。如果使用范围解析运算符 ( ::),您需要更多关于上下文的信息(我们是否已经在对象上下文中?我们是否在对象之外?等)。

回答by MrZebra

self(not $self) refers to the typeof class, where as $thisrefers to the current instanceof the class. selfis for use in static member functions to allow you to access static member variables. $thisis used in non-static member functions, and is a reference to the instance of the class on which the member function was called.

self(不是 $self) 是指类的类型,其中 as$this是指类的当前实例self用于静态成员函数以允许您访问静态成员变量。$this用于非静态成员函数,并且是对调用成员函数的类的实例的引用。

Because thisis an object, you use it like: $this->member

因为this是一个对象,你可以像这样使用它:$this->member

Because selfis not an object, it's basically a type that automatically refers to the current class, you use it like: self::member

因为self它不是一个对象,它基本上是一个自动引用当前类的类型,你可以像这样使用它:self::member

回答by lo_fye

$this->is used to refer to a specific instance of a class's variables (member variables) or methods.

$this->用于引用类的变量(成员变量)或方法的特定实例。

Example: 
$derek = new Person();

$derek is now a specific instance of Person. Every Person has a first_name and a last_name, but $derek has a specific first_name and last_name (Derek Martin). Inside the $derek instance, we can refer to those as $this->first_name and $this->last_name

$derek 现在是 Person 的一个特定实例。每个 Person 都有一个 first_name 和一个 last_name,但 $derek 有一个特定的 first_name 和 last_name (Derek Martin)。在 $derek 实例中,我们可以将它们称为 $this->first_name 和 $this->last_name

ClassName:: is used to refer to that type of class, and its static variables, static methods. If it helps, you can mentally replace the word "static" with "shared". Because they are shared, they cannot refer to $this, which refers to a specific instance (not shared). Static Variables (i.e. static $db_connection) can be shared among all instances of a type of object. For example, all database objects share a single connection (static $connection).

ClassName:: 用于引用该类型的类及其静态变量、静态方法。如果有帮助,您可以在精神上将“静态”一词替换为“共享”。因为它们是共享的,所以它们不能引用 $this,它指的是一个特定的实例(不共享)。静态变量(即静态 $db_connection)可以在一种对象类型的所有实例之间共享。例如,所有数据库对象共享一个连接(静态 $connection)。

Static Variables Example:Pretend we have a database class with a single member variable: static $num_connections; Now, put this in the constructor:

静态变量示例:假设我们有一个带有单个成员变量的数据库类:static $num_connections; 现在,把它放在构造函数中:

function __construct()
{
    if(!isset $num_connections || $num_connections==null)
    {
        $num_connections=0;
    }
    else
    {
        $num_connections++;
    }
}

Just as objects have constructors, they also have destructors, which are executed when the object dies or is unset:

就像对象有构造函数一样,它们也有析构函数,它们在对象死亡或未设置时执行:

function __destruct()
{
    $num_connections--;
}

Every time we create a new instance, it will increase our connection counter by one. Every time we destroy or stop using an instance, it will decrease the connection counter by one. In this way, we can monitor the number of instances of the database object we have in use with:

每次我们创建一个新实例时,它都会将我们的连接计数器增加一。每次我们销毁或停止使用一个实例时,它都会将连接计数器减一。通过这种方式,我们可以监控我们正在使用的数据库对象的实例数量:

echo DB::num_connections;

Because $num_connections is static (shared), it will reflect the total number of active database objects. You may have seen this technique used to share database connections among all instances of a database class. This is done because creating the database connection takes a long time, so it's best to create just one, and share it (this is called a Singleton Pattern).

因为 $num_connections 是静态的(共享的),它将反映活动数据库对象的总数。您可能已经看到这种技术用于在数据库类的所有实例之间共享数据库连接。这样做是因为创建数据库连接需要很长时间,所以最好只创建一个并共享它(这称为单例模式)。

Static Methods (i.e. public static View::format_phone_number($digits)) can be used WITHOUT first instantiating one of those objects (i.e. They do not internally refer to $this).

可以使用静态方法(即 public static View::format_phone_number($digits))而无需首先实例化这些对象之一(即它们不在内部引用 $this)。

Static Method Example:

静态方法示例:

public static function prettyName($first_name, $last_name)
{
    echo ucfirst($first_name).' '.ucfirst($last_name);
}

echo Person::prettyName($derek->first_name, $derek->last_name);

As you can see, public static function prettyName knows nothing about the object. It's just working with the parameters you pass in, like a normal function that's not part of an object. Why bother, then, if we could just have it not as part of the object?

如您所见,公共静态函数prettyName 对对象一无所知。它只是处理你传入的参数,就像一个不属于对象的普通函数。那么,如果我们可以不将它作为对象的一部分,为什么还要麻烦呢?

  1. First, attaching functions to objects helps you keep things organized, so you know where to find them.
  2. Second, it prevents naming conflicts. In a big project, you're likely to have two developers create getName() functions. If one creates a ClassName1::getName(), and the other creates ClassName2::getName(), it's no problem at all. No conflict. Yay static methods!
  1. 首先,将函数附加到对象可以帮助您保持组织有序,因此您知道在哪里可以找到它们。
  2. 其次,它可以防止命名冲突。在一个大项目中,您可能有两个开发人员创建 getName() 函数。如果一个创建一个 ClassName1::getName(),另一个创建 ClassName2::getName(),那完全没有问题。没有冲突。是的静态方法!

SELF::If you are coding outsidethe object that has the static method you want to refer to, you must call it using the object's name View::format_phone_number($phone_number); If you are coding insidethe object that has the static method you want to refer to, you can eitheruse the object's name View::format_phone_number($pn), OR you can use the self::format_phone_number($pn) shortcut

SELF::如果您在具有要引用的静态方法的对象之外进行编码,则必须使用对象的名称来调用它。 View::format_phone_number($phone_number); 如果您在编码里面有你要引用,可以在静态方法的对象要么使用对象的名称查看:: format_phone_number($ PN),或者你可以使用自助:: format_phone_number($ PN)的快捷方式

The same goes for static variables: Example:View::templates_path versus self::templates_path

静态变量也是如此: 示例:View::templates_path 与 self::templates_path

Inside the DB class, if we were referring to a static method of some other object, we would use the object's name: Example:Session::getUsersOnline();

在 DB 类中,如果我们引用某个其他对象的静态方法,我们将使用该对象的名称: 示例:Session::getUsersOnline();

But if the DB class wanted to refer to its own static variable, it would just say self: Example:self::connection;

但是如果 DB 类想要引用它自己的静态变量,它只会说 self: Example:self::connection;

Hope that helps clear things up :)

希望这有助于澄清事情:)

回答by okconfused

From this blog post:

来自这篇博文

  • selfrefers to the current class
  • selfcan be used to call static functions and reference static member variables
  • selfcan be used inside static functions
  • selfcan also turn off polymorphic behavior by bypassing the vtable
  • $thisrefers to the current object
  • $thiscan be used to call static functions
  • $thisshould not be used to call static member variables. Use selfinstead.
  • $thiscan not be used inside static functions
  • self指当前类
  • self可用于调用静态函数和引用静态成员变量
  • self可以在静态函数中使用
  • self也可以通过绕过 vtable 来关闭多态行为
  • $this引用当前对象
  • $this可用于调用静态函数
  • $this不应用于调用静态成员变量。使用self来代替。
  • $this不能在静态函数中使用

回答by ramin rostami

In PHP, you use the self keyword to access static properties and methods.

在 PHP 中,您使用 self 关键字来访问静态属性和方法。

The problem is that you can replace $this->method()with self::method()anywhere, regardless if method()is declared static or not. So which one should you use?

问题是你可以$this->method()self::method()任何地方替换,无论是否method()声明为静态。那么你应该使用哪一个?

Consider this code:

考虑这个代码:

class ParentClass {
    function test() {
        self::who();    // will output 'parent'
        $this->who();   // will output 'child'
    }

    function who() {
        echo 'parent';
    }
}

class ChildClass extends ParentClass {
    function who() {
        echo 'child';
    }
}

$obj = new ChildClass();
$obj->test();

In this example, self::who()will always output ‘parent', while $this->who()will depend on what class the object has.

在这个例子中,self::who()将始终输出 'parent',而$this->who()将取决于对象具有的类。

Now we can see that self refers to the class in which it is called, while $thisrefers to the class of the current object.

现在我们可以看到 self 指的是调用它的类,而$this的是当前对象

So, you should use self only when $thisis not available, or when you don't want to allow descendant classes to overwrite the current method.

所以,你应该只在$this不可用时使用 self ,或者当你不想让后代类覆盖当前方法时。

回答by Tarun Singhal

Inside a class definition, $thisrefers to the current object, while selfrefers to the current class.

在类定义中,$this指的是当前对象,而self指的是当前类。

It is necessary to refer to a class element using self, and refer to an object element using $this.

需要使用 来引用类元素,使用 来self引用对象元素$this

self::STAT // refer to a constant value
self::$stat // static variable
$this->stat // refer to an object variable  

回答by cruizer

According to http://www.php.net/manual/en/language.oop5.static.phpthere is no $self. There is only $this, for referring to the current instance of the class (the object), and self, which can be used to refer to static members of a class. The difference between an object instance and a class comes into play here.

根据http://www.php.net/manual/en/language.oop5.static.php没有$self. 只有$this, 用于引用类(对象)的当前实例,而 self 可用于引用类的静态成员。对象实例和类之间的区别在这里发挥作用。