|
|
"Paamayim Nekudotayim" или просто "двойное двоеточие".
Используя эту лексему, программист может обращаться к
константам,
статическим или
перегруженным свойствам или методам класса.
При обращении к этим элементам извне класса, программист должен
использовать имя этого класса.
"Paamayim Nekudotayim" на первый взгляд может показаться странным
словосочетанием для обозначения двойного двоеточия. Однако,
во время создания Zend Engine версии 0.5 (который входил в PHP3),
Andi и Zeev выбрали именно это обозначение.
"Paamayim Nekudotayim" действительно значит "двойное двоеточие". На иврите.
Просто это обозначение не менялось ни разу в течение всего
времени разработки PHP.
Пример 19-12. Использование :: вне объявления класса |
<?php
class MyClass {
const CONST_VALUE = 'Значение константы';
}
echo MyClass::CONST_VALUE;
?>
|
|
Для обращения к свойствам и методам в объявлении класса
используются ключевые слова self и parent.
Пример 19-13. Использование :: в объявлении класса |
<?php
class OtherClass extends MyClass {
public static $my_static = 'статическая переменная';
public static function doubleColon() {
echo parent::CONST_VALUE . "\n";
echo self::$my_static . "\n";
}
}
OtherClass::doubleColon();
?>
|
|
Когда дочерний класс перегружает методы, объявленные в классе-родителе,
PHP не будет осуществлять автоматический вызов методов, принадлежащих
классу-родителю. Этот функционал возлагается на метод, перегружаемый
в дочернем классе. Данное правило распространяется на конструкторы и деструкторы, перегруженные и "волшебные" методы.
Пример 19-14. Обращение к методу в родительском классе |
<?php
class MyClass {
protected function myFunc() {
echo "MyClass::myFunc()\n";
}
}
class OtherClass extends MyClass {
public function myFunc() {
parent::myFunc();
echo "OtherClass::myFunc()\n";
}
}
$class = new OtherClass();
$class->myFunc();
?>
|
|
Anonymous
16-Oct-2007 03:41
There's no surprize here. These resolution rules are identical in C++ and Java, where static fields (and methods) are not separately instanciated within the inheritance tree for the new derived classes.
This is per design. If you want per-class static fields,you have to overload each static field (or method) to assign them a new value that will hide the inherited static field (or method). The "$self::" scope in a static method does not refer to the object or class from which the method is called, as it is statically compiled and resolved within the class declaring the method.
In other words "$self::" is just needed to specify the field declared in the defining class, instead of a homonym variable (or function) in the local scope which may hide it. This is exactly similar to the "this." scope specifier (used with the "." operator here) used in C++ (or Java).
The same can be said about the semantic of "$super::" used within a static method (similar to "super." scope specifier used in C++ or Java).
Neither PHP, nor C++, have a way to work on instanciated class objects as if they were objects of the first grade (that's why C++ and Java are making distinctions between classes and interfaces).
On the opposite Javascript/ECMAScript defines classes like standard objects with a "prototype" field for the fields (or methods) to inherit instead of duplicating them with the new operator. When working in PHP, forget Javascript, think like in C++ and Java.
mongoose643 at gmail dot com
13-Feb-2007 12:11
This is a solution for those that still need to write code compatible with php 4 but would like to use the flexibility of static variables. PHP 4 does not support static variables within the class scope but it does support them within the scope of class methods. The following is a bit of a workaround to store data in static mode in php 4.
Note: This code also works in PHP 5.
(Tested on version 4.3.1+)
The tricky part is when using when arrays you have to do a bit of fancy coding to get or set individual elements in the array. The example code below should show you the basics of it though.
<?php
class StaticSample
{
function &s_foo($value=null, $remove=null)
{
static $s_var; if($remove)
{
if(is_array($value))
{
if(is_array($s_var))
{
foreach($value as $key => $data)
{
unset($s_var[$key]);
}
}
}
else
{
$s_var = null;
unset($s_var);
}
$value = null;
}
if($value)
{
if(is_array($value))
{
if(is_array($s_var))
{
foreach($value as $key => $data)
{
$s_var[$key] = $data; }
}
else
{
$s_var = $value;
}
}
else
{
$s_var = $value;
}
}
return $s_var;
}
}
echo "Working with non-array values.<br>";
echo "Before Setting: ".StaticSample::s_foo();
echo "<br>";
echo "While Setting: ".StaticSample::s_foo("VALUE HERE");
echo "<br>";
echo "After Setting: ".StaticSample::s_foo();
echo "<br>";
echo "While Removing: ".StaticSample::s_foo(null, 1);
echo "<br>";
echo "After Removing: ".StaticSample::s_foo();
echo "<hr>";
echo "Working with array values<br>";
$array = array(0=>"cat", 1=>"dog", 2=>"monkey");
echo "Set an array value: ";
print_r(StaticSample::s_foo($array));
echo "<br>";
$all_elements = StaticSample::s_foo();
$middle_element = $all_elements[1];
echo "The middle element: ".$middle_element;
echo "<br>";
$changed_array = array(1=>"big dog", 3=>"bat", "bird"=>"flamingo");
echo "Changing the value: ";
print_r(StaticSample::s_foo($changed_array));
echo "<br>";
$element_to_erase = array(3=>null);
echo "Erasing the fourth element: ";
$elements_left = StaticSample::s_foo($element_to_erase, 1);
print_r($elements_left);
echo "<br>";
echo "Enjoy!";
?>
dexen at google dot me dot up
22-Sep-2006 07:40
``self'' and ``parent'' are valid arguments to the ``new'' operator. All the constructor stuff works as expected. Example:
<?php
class Foo {}
class Bar extends Foo {
static function test() {
return(
array(
new self,
new self(),
new parent( 'a', 1 ),
) );
}
}
print_r( Bar::test() ); ?>
Calling Bar::test() gives you nice list of three instances. ( i'm describing it there, as it was a suprise to me. ) Maybe you can find it usefull, for example, in some generic ::__clone() method that works across inheritance tree.
developit at mail dot ru
27-Jan-2006 03:57
You use 'self' to access this class, 'parent' - to access parent class, and what will you do to access a parent of the parent? Or to access the very root class of deep class hierarchy? The answer is to use classnames. That'll work just like 'parent'. Here's an example to explain what I mean. Following code
<?php
class A
{
protected $x = 'A';
public function f()
{
return '['.$this->x.']';
}
}
class B extends A
{
protected $x = 'B';
public function f()
{
return '{'.$this->x.'}';
}
}
class C extends B
{
protected $x = 'C';
public function f()
{
return '('.$this->x.')'.parent::f().B::f().A::f();
}
}
$a = new A();
$b = new B();
$c = new C();
print $a->f().'<br/>';
print $b->f().'<br/>';
print $c->f().'<br/>';
?>
will output
[A] -- {B} -- (C){C}{C}[C]
Kristof Coomans
25-Nov-2005 03:08
In response to ian at [first name]henderson dot org:
(related bogus bug report: http://bugs.php.net/bug.php?id=26930)
The functionality you've expected maybe will be possible in PHP6, probably by using the static keyword in conjunction with the scope resolution parameter. You can read more about this in the minutes of the PHP developers meeting at 11 and 12 november in Paris: http://www.php.net/~derick/meeting-notes.html point 5.4: Late static binding using "this" without "$" (or perhaps with a different name)
zeldorblat at gmail dot com
07-Sep-2005 09:47
The alternative to john at johnjosephbachir dot org's suggestion without using eval():
call_user_func(array($classname, 'a_static_function'));
john at johnjosephbachir dot org
30-Aug-2005 03:23
A way to achieve Doug's last example
<?php
$classname::a_static_function();
?>
is to use eval():
<?php
$string = $classname.'::a_static_function();';
eval($sting);
?>
Remember to include a semicolon inside the string passed to eval().
doug at douglassdavis dot com
29-Aug-2005 07:52
Just a note that while this works for new objects:
<?php
$obj = new $classname();
?>
and this works to call a function:
<?php
$functionname();
?>
this does not work to call static functions, you will get a parse error:
<?php
$classname::a_static_function();
?>
thenewparadigm at hotmail dot com
05-Mar-2005 09:43
There is also a quirk with using the scope resolution operator on static class variables. Below is an example using a highly modified version of Ian's code:
<?php
class ExampleSuperclass
{
static $className;
static function showClassName() {
echo self::$className . "\n";
}
}
class ExampleSubclassOne extends ExampleSuperclass
{
static function setClassName()
{
self::$className = "subclassOne";
}
}
class ExampleSubclassTwo extends ExampleSuperClass
{
static function setClassName()
{
self::$className = "subclassTwo";
}
}
ExampleSubclassOne::setClassName();
ExampleSubclassTwo::setClassName();
ExampleSubclassOne::showClassName(); echo ExampleSubclassOne::$className . "\n"; echo ExampleSubclassTwo::$className . "\n"; echo ExampleSuperclass::$className . "\n"; ?>
appearantly, any static variables defined in a superclass are directly referenced in subclasses,
and all changes are visible throughout the class heirarchy. care must be taken when using static
class variables.
ian at [first name]henderson dot org
31-Jan-2005 10:43
Please note that methods called by the scope resolution operator which are defined by a superclass of the first operand are called in the scope of the SUPERCLASS. For example,
<?php
class ExampleSuperclass
{
static function classType()
{
return "superclass";
}
static function doSomething()
{
echo "doing something with " . self::classType();
}
}
class ExampleClass extends ExampleSuperclass
{
static function classType()
{
return "subclass";
}
}
ExampleClass::doSomething();
?>
This can be surprising (it surprised me!) when coming from other object-oriented languages, which would output "doing something with subclass" in this case.
|