When to use self over $this?

前端 未结 23 2828
醉梦人生
醉梦人生 2020-11-21 11:19

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

When is each appropriate?

相关标签:
23条回答
  • 2020-11-21 12:21

    DO NOT USE self::, use 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:

    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:

    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.

    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.

    See PHP Documentation

    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

    0 讨论(0)
  • 2020-11-21 12:21

    Additionally since $this:: has not been discussed yet.

    For informational purposes only, as of PHP 5.3 when dealing with instantiated objects to get the current scope value, as opposed to using static::, one can alternatively use $this:: like so.

    http://ideone.com/7etRHy

    class Foo
    {
        const NAME = 'Foo';
    
        //Always Foo::NAME (Foo) due to self
        protected static $staticName = self::NAME;
    
        public function __construct()
        {
            echo $this::NAME;
        }
    
        public function getStaticName()
        {
           echo $this::$staticName;
        }
    }
    
    class Bar extends Foo
    {
        const NAME = 'FooBar';
    
        /**
         * override getStaticName to output Bar::NAME
         */
        public function getStaticName()
        {
            $this::$staticName = $this::NAME;
            parent::getStaticName();
        }
    }
    
    $foo = new Foo; //outputs Foo
    $bar = new Bar; //outputs FooBar
    $foo->getStaticName(); //outputs Foo
    $bar->getStaticName(); //outputs FooBar
    $foo->getStaticName(); //outputs FooBar
    

    Using the code above is not common or recommended practice, but is simply to illustrate its usage, and is to act as more of a "Did you know?" in reference to the original poster's question.

    It also represents the usage of $object::CONSTANT for example echo $foo::NAME; as opposed to $this::NAME;

    0 讨论(0)
  • 2020-11-21 12:23

    The keyword self does NOT refer 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, self also 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.

    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 $this pointer, 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 $this pointer within the called functions.

    0 讨论(0)
  • 2020-11-21 12:23

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

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

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

    0 讨论(0)
  • 2020-11-21 12:23

    I believe question was not whether you can call the static member of the class by calling ClassName::staticMember. Question was what's the difference between using self::classmember and $this->classmember.

    For e.g., both of the following examples work without any errors, whether you use self:: or $this->

    class Person{
        private $name;
        private $address;
    
        public function __construct($new_name,$new_address){
            $this->name = $new_name;
            $this->address = $new_address;
        }
    }
    
    class Person{
        private $name;
        private $address;
        public function __construct($new_name,$new_address){
            self::$name = $new_name;
            self::$address = $new_address;
        }
    }
    
    0 讨论(0)
提交回复
热议问题