Ccna final exam - java, php, javascript, ios, cshap all in one. This is a collaboratively edited question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.
Friday, May 25, 2012
PHP: self vs. $this
In PHP5, what is the difference between using self and $this ? When is each appropriate?
From http://www.phpbuilder.com/board/showthread.php?t=10354489:
Use $this to refer to the current object. Use self to refer to the current class. In other words, use $this->member for non-static members, use self::$member for static members.
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 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.
"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
$this-> is used to refer to a specific instance of a class's variables (member variables) or methods.
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
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).
Static Variables Example: Pretend we have a database class with a single member variable: static $num_connections; Now, put this in the constructor:
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).
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).
Static Method Example:
public static function prettyName($first_name, $last_name) { echo ucfirst($first_name).' '.ucfirst($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?
First, attaching functions to objects helps you keep things organized, so you know where to find them. 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!
SELF:: If you are coding outside the 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 inside the object that has the static method you want to refer to, you can either use the object's name View::format_phone_number($pn), OR you can use the self::format_phone_number($pn) shortcut
The same goes for static variables: Example: View::templates_path versus 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();
But if the DB class wanted to refer to its own static variable, it would just say self: Example: self::connection;
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::getStatus() 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 its 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.
According to http://www.php.net/manual/en/language.oop5.static.php there 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.
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; } }
From http://www.phpbuilder.com/board/showthread.php?t=10354489:
ReplyDeleteUse $this to refer to the current
object. Use self to refer to the
current class. In other words, use
$this->member for non-static members,
use self::$member for static members.
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 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.
ReplyDeleteclass 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.
"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.
ReplyDeleteBecause "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
$this-> is used to refer to a specific instance of a class's variables (member variables) or methods.
ReplyDeleteExample:
$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
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).
Static Variables Example:
Pretend we have a database class with a single member variable: static $num_connections;
Now, put this in the constructor:
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).
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).
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?
First, attaching functions to objects helps you keep things organized, so you know where to find them.
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!
SELF::
If you are coding outside the 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 inside the object that has the static method you want to refer to, you can either use the object's name View::format_phone_number($pn), OR you can use the self::format_phone_number($pn) shortcut
The same goes for static variables:
Example: View::templates_path versus 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();
But if the DB class wanted to refer to its own static variable, it would just say self:
Example: self::connection;
Hope that helps clear things up :)
DO NOT USE SELF:: use STATIC::
ReplyDeleteThere 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::getStatus() 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 its 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.
http://php.net/manual/en/language.oop5.late-static-bindings.php
According to http://www.php.net/manual/en/language.oop5.static.php there 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.
ReplyDeleteI 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.
ReplyDeleteFor 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;
}
}
Here is an example of correct usage of $this and self for non-static
ReplyDeleteand static member variables:
<?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();
?>