четверг, 19 декабря 2013 г.

Разница между $this и self в PHP. Подробная версия.


У каждого обычно возникает вопрос, что такое $this, что такое self, для чего они используются и в чем разница между ними?
ПРАВИЛА КОТОРЫЕ ВЫ ДОЛЖНЫ ЗАПОМНИТЬ:

  1. Статические функции должны использовать только статические переменные.
  2. self ТОЛЬКО для статических функций, свойств. Но также можно вызвать нестатический метод, КАК СТАТИЧЕСКИЙ через self. Но лучше так не делать, а то папа побьет.
  3. this ТОЛЬКО для нестатических.
  4. this требует, чтобы класс был проинстанцирован, self не требует.

$this - это ССЫЛКА на ТЕКУЩИЙ объект и она нужна, чтобы обратиться к переменной в КОНТЕКСТЕ класса. К примеру:

class human {
     public $name;
     public function klassFunc() {};
     function getName() {
            echo $name; // неправильно, обратиться не к переменной public name
            echo $this->name; // правильно
            
            //вызов метода класса
            $this->klassFunc();
     }
}

Обычна нужна, чтобы инициализировать поля в конструкторе, ну и не только:

class human {
     public $name;   
     public function __construct($name){
          $this->name = $name;
          $name = $name; //будет ошибка
     }
}

$self используется в том, же самом ключе, но уже для СТАТИЧЕСКИХ свойств:

class human {
     static $name = "ololo";
     
     public function klassFunc() {};
     function getName() {
            echo self::$name; //обращение к name
            echo $this->name; //null или ошибка. НЕЛЬЗЯ
     }
}

Проверочная программа которая показывает главную разницу между self и $this:

class Klass {
const       
STAT 'S' // константы всегда статичныstatic     $stat 'Static' ;
public     
$publ 'Public' ;
private    
$priv 'Private' ;
protected  
$prot 'Protected' ;

function 
__construct( ){  }

public function 
show( ){
    print 
'<br> self::STAT: '.self::STAT// ссылается на константу
    
print '<br> self::$stat: '.self::$stat// статическая переменная.
    
print '<br>$this->stat: '.$this->stat // Ошибки нет, но выведет пустую строку. ПРЕДУПРЕЖДЕНИЕ.
    
print '<br>$this->publ: '.$this->publ // выведет как надо
    
print '<br>' ;
}
}
$me = new Klass() ;$me->show() ;

Результат:
self::STAT: S
self::$stat: Static
Strict Standards: Accessing static property Klass::$stat as non static in htdocs\test\testReference.php on line ..
Notice: Undefined property: Klass::$stat in C:\xampp\htdocs\test\testReference.php on line 50
$this->stat:
$this->publ: Public
Видно, что php умный и кидает предупреждения глупым программистам. Не делайте так.

Второе главное отличие состоит в том, что

self не использует таблицу виртуальных методов, то есть:
(взято с StackOverflow)

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();
Выведет:

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

Пояснение:
Метод sayHello использует this, поэтому виртуальная таблица вызовет Geek::getTitle()
Метод sayGoodbye использует self, поэтому виртуальная таблица будет не задействована и будет вызван parent::getTitle()

Решение:
Используем вместо self, static keyword:
public function sayGoodbye() {
      echo "Goodbye from ".static::getTitle();

Всем, спасибо, за внимание :)

11 коммент.:

я расширил свой кругозор в PHP. спасибо Автор!

Спасибо! Очень круто.

Что значит "класс ПРОИНСТАНЦИРОВАН" в 4м пункте? Нигде не нашёл такого понятия. Имеется ввиду, "инициализиван"?

class human {
static $name = "ololo";

public function klassFunc() {}; // ; ошибка
function getName() {
echo self::$name; //обращение к name
echo $this->name; //null или ошибка. НЕЛЬЗЯ
}
}

Добрый день!

Поправьте, пожалуйста:

const STAT = 'S' ; // константы всегда статичныstatic $stat = 'Static' ;

А то слегка непонятно. Спасибо

Автор крут, согласен!

Вставьте код хотя бы в http://phpfiddle.org/
В каком мест еавтор крут?

Этот комментарий был удален автором.

Вот что выяснил
1.Из статической функции обращаться к свойствам можно только через self::
2.Из статической функции нельзя вызвать нестатическое свойство
3.self:: не работает в нестатической функции и нестатическом свойстве
4.$this:: не работает для обращения к нестатическому свойству, только $this->
5.из нестатической функции обратиться к статическому свойству можно $this:: или self::
6.из нестатической функции обратиться к статическому свойству нельзя с помощью $this-> */


2й пункт.
class M {
public $table=2;
public static function C(){
echo self::$table; }//$this::$table тоже не работает
}

$o=new M();
$o->C(); //$o::C(); M::C(); - варианты при статической функции

не работает.

Strange "water hack" burns 2lbs overnight

Well over 160000 women and men are using a simple and secret "water hack" to burn 1-2lbs every night in their sleep.

It is effective and it works every time.

You can do it yourself by following these easy steps:

1) Take a glass and fill it with water half glass

2) And now follow this crazy HACK

and become 1-2lbs thinner in the morning!

Отправить комментарий