CLASSES and OBJECTS that represent the "Ideal World"
Wouldn't it be great to get the lawn mowed by saying $son->mowLawn()? Assuming the function mowLawn() is defined, and you have a son that doesn't throw errors, the lawn will be mowed.
In the following example; let objects of type Line3D measure their own length in 3-dimensional space. Why should I or PHP have to provide another method from outside this class to calculate length, when the class itself holds all the neccessary data and has the education to make the calculation for itself?
<?php
/*
* Point3D.php
*
* Represents one locaton or position in 3-dimensional space
* using an (x, y, z) coordinate system.
*/
class Point3D
{
public $x;
public $y;
public $z; // the x coordinate of this Point.
/*
* use the x and y variables inherited from Point.php.
*/
public function __construct($xCoord=0, $yCoord=0, $zCoord=0)
{
$this->x = $xCoord;
$this->y = $yCoord;
$this->z = $zCoord;
}
/*
* the (String) representation of this Point as "Point3D(x, y, z)".
*/
public function __toString()
{
return 'Point3D(x=' . $this->x . ', y=' . $this->y . ', z=' . $this->z . ')';
}
}
/*
* Line3D.php
*
* Represents one Line in 3-dimensional space using two Point3D objects.
*/
class Line3D
{
$start;
$end;
public function __construct($xCoord1=0, $yCoord1=0, $zCoord1=0, $xCoord2=1, $yCoord2=1, $zCoord2=1)
{
$this->start = new Point3D($xCoord1, $yCoord1, $zCoord1);
$this->end = new Point3D($xCoord2, $yCoord2, $zCoord2);
}
/*
* calculate the length of this Line in 3-dimensional space.
*/
public function getLength()
{
return sqrt(
pow($this->start->x - $this->end->x, 2) +
pow($this->start->y - $this->end->y, 2) +
pow($this->start->z - $this->end->z, 2)
);
}
/*
* The (String) representation of this Line as "Line3D[start, end, length]".
*/
public function __toString()
{
return 'Line3D[start=' . $this->start .
', end=' . $this->end .
', length=' . $this->getLength() . ']';
}
}
/*
* create and display objects of type Line3D.
*/
echo '<p>' . (new Line3D()) . "</p>\n";
echo '<p>' . (new Line3D(0, 0, 0, 100, 100, 0)) . "</p>\n";
echo '<p>' . (new Line3D(0, 0, 0, 100, 100, 100)) . "</p>\n";
?>
<-- The results look like this -->
Line3D[start=Point3D(x=0, y=0, z=0), end=Point3D(x=1, y=1, z=1), length=1.73205080757]
Line3D[start=Point3D(x=0, y=0, z=0), end=Point3D(x=100, y=100, z=0), length=141.421356237]
Line3D[start=Point3D(x=0, y=0, z=0), end=Point3D(x=100, y=100, z=100), length=173.205080757]
My absolute favorite thing about OOP is that "good" objects keep themselves in check. I mean really, it's the exact same thing in reality... like, if you hire a plumber to fix your kitchen sink, wouldn't you expect him to figure out the best plan of attack? Wouldn't he dislike the fact that you want to control the whole job? Wouldn't you expect him to not give you additional problems? And for god's sake, it is too much to ask that he cleans up before he leaves?
I say, design your classes well, so they can do their jobs uninterrupted... who like bad news? And, if your classes and objects are well defined, educated, and have all the necessary data to work on (like the examples above do), you won't have to micro-manage the whole program from outside of the class. In other words... create an object, and LET IT RIP!
Die Grundlagen
class
Jede Klassendefinition beginnt mit dem Schlüsselwort class, gefolgt von
einem Klassennamen, welcher ein beliebiger Name sein kann, der kein
reservierter Bezeichner von PHP ist.
Darauf folgt ein Paar geschweifter Klammern, die die Definitionen der
Klassenmember und Methoden enthalten. Die Pseudovariable
$this ist verfügbar, falls eine Methode aus einem
Objektkontext heraus aufgerufen wird. $this ist eine
Referenz auf das aufrufende Objekt (üblicherweise das Objekt zu dem die
Methode gehört, es kann sich aber auch um ein anderes Objekt handeln, falls
die Methode statisch aus dem
Kontext eines zusätzlichen Objektes aufgerufen wird). Dies wird anhand
der nachfolgenden Beispiele erläutert:
Beispiel #1 $this Variable in objektorientierter Programmierung Das oben gezeigte Beispiel erzeugt folgende
Ausgabe:
<?php
class A
{
function foo()
{
if (isset($this)) {
echo '$this ist definiert (';
echo get_class($this);
echo ")\n";
} else {
echo "\$this ist nicht definiert.\n";
}
}
}
class B
{
function bar()
{
A::foo();
}
}
$a = new A();
$a->foo();
A::foo();
$b = new B();
$b->bar();
B::bar();
?>
$this ist definiert (A)
$this ist nicht definiert.
$this ist definiert (B)
$this ist nicht definiert.
Beispiel #2 Einfache Klassendefinition
<?php
class SimpleClass
{
// Memberdeklaration
public $var = 'ein Vorgabewert';
// Methodendeklaration
public function displayVar() {
echo $this->var;
}
}
?>
Der Standardwert muss ein konstanter Ausdruck sein, keine (z.B.) variable, Klassenattribut oder Funktionsaufruf.
Beispiel #3 Standradwerte von Klassenattributen
<?php
class SimpleClass
{
// ungültige Attributdeklarationen:
public $var1 = 'hallo '.'welt';
public $var2 = <<<EOD
hallo welt
EOD;
public $var3 = 1+2;
public $var4 = self::myStaticMethod();
public $var5 = $myVar;
// gültige Attributdeklarationen
public $var6 = myConstant;
public $var7 = self::classConstant;
public $var8 = array(true, false);
}
?>
Hinweis: Es gibt nette Funktionen, um Klassen und Objekte zu behandeln. Sie möchten vielleicht einen Blick auf Klassen/Objekte werfen.
new
Um eine Instanz einer Klasse zu erzeugen, muss ein neues Objekt erzeugt und einer Variablen zugewiesen werden. Bei der Erzeugung wird das Objekt immer zugewiesen, außer wenn das Objekt einen definierten Konstruktor besitzt, der aufgrund eines Fehlers eine Exception wirft. Klassen sollten vor ihrer Instantiierung definiert werden (in manchen Fällen ist dies eine Notwendigkeit).
Beispiel #4 Eine Instanz erzeugen
<?php
$instanz = new SimpleClass();
?>
Im Kontext einer Klasse ist es möglich neue Objekte mit new self und new parent anzulegen.
Wenn man eine bereits erzeugte Instanz einer Klasse einer neuen Variablen zuweist, wird die neue Variable auf die selbe Instanz zugreifen wie das Objekt, das zugewiesen wurde. Dieses Verhalten ist das selbe, wenn man Instanzen an Funktionen übergibt. Eine Kopie eines bereits erzeugten Objektes erhält man, indem man es klont.
Beispiel #5 Objektzuweisung
<?php
$zugewiesen = $instanz;
$referenz =& $instanz;
$instanz->var = '$zugewiesen wird diesen Wert haben';
$instanz = null; // $instanz und $referenz werden null
var_dump($instanz);
var_dump($referenz);
var_dump($zugewiesen);
?>
Das oben gezeigte Beispiel erzeugt folgende Ausgabe:
NULL NULL object(SimpleClass)#1 (1) { ["var"]=> string(30) "$zugewiesen wird diesen Wert haben" }
extends
Eine Klasse kann Methoden und Member einer anderen Klasse erben, indem man das extends Schlüsselwort in der Deklaration benutzt. Es ist nicht möglich, mehrere Klassen zu erweitern, eine Klasse kann nur eine einzige Basisklasse beerben.
Die ererbten Methoden - es sei denn Sie wurden von der Vaterklasse als final definiert - und Member können überschrieben werden, indem Sie mit dem selben Namen wie in der Vaterklasse erneut deklariert werden. Es ist möglich, auf die überschriebene Methoden oder statische Member zuzugreifen, wenn diese mittels parent:: referenziert werden.
Beispiel #6 Einfache Vererbung
<?php
class ExtendClass extends SimpleClass
{
// Die Vatermethode überschreiben
function displayVar()
{
echo "Erweiternde Klasse\n";
parent::displayVar();
}
}
$extended = new ExtendClass();
$extended->displayVar();
?>
Das oben gezeigte Beispiel erzeugt folgende Ausgabe:
Erweiternde Klasse ein Vorgabewert
Die Grundlagen
21-Aug-2008 02:11
24-May-2008 02:35
@info -- 20-April
This is because you requested class "b" before defining it, not because you defined class "b" before "a". It doesn't make a difference which class you define first.
20-Apr-2008 11:40
if you do this
<?php
$x = new b();
class b extends a {}
class a { }
?>
PHP will tell you "class b not found", because you've defined class b before a. However, the error tells you something different.... Got me a little confused :)
15-Feb-2008 02:16
If you just want to create a new object that extends another object and you want to copy all variables from the father object, you may use this piece of code:
<?php
$father =& new father();
$father->a_var = "Hello World.";
$son = new son($event);
$son->say_hello();
class father {
public $a_var;
}
class son extends father {
public function __construct($father_class) {
foreach ($father_class as $variable=>$value) {
$this->$variable = $value;
}
}
public function say_hello() {
echo "Son says: ".$this->a_var;
}
}
?>
This outputs:
Son says: Hello World.
So you dont have to clone the entire object to get the contents of the variables from the father object.
16-Dec-2007 02:46
I was confused at first about object assignment, because it's not quite the same as normal assignment or assignment by reference. But I think I've figured out what's going on.
First, think of variables in PHP as data slots. Each one is a name that points to a data slot that can hold a value that is one of the basic data types: a number, a string, a boolean, etc. When you create a reference, you are making a second name that points at the same data slot. When you assign one variable to another, you are copying the contents of one data slot to another data slot.
Now, the trick is that object instances are not like the basic data types. They cannot be held in the data slots directly. Instead, an object's "handle" goes in the data slot. This is an identifier that points at one particular instance of an obect. So, the object handle, although not directly visible to the programmer, is one of the basic datatypes.
What makes this tricky is that when you take a variable which holds an object handle, and you assign it to another variable, that other variable gets a copy of the same object handle. This means that both variables can change the state of the same object instance. But they are not references, so if one of the variables is assigned a new value, it does not affect the other variable.
<?php
// Assignment of an object
Class Object{
public $foo="bar";
};
$objectVar = new Object();
$reference =& $objectVar;
$assignment = $objectVar
//
// $objectVar --->+---------+
// |(handle1)----+
// $reference --->+---------+ |
// |
// +---------+ |
// $assignment -->|(handle1)----+
// +---------+ |
// |
// v
// Object(1):foo="bar"
//
?>
$assignment has a different data slot from $objectVar, but its data slot holds a handle to the same object. This makes it behave in some ways like a reference. If you use the variable $objectVar to change the state of the Object instance, those changes also show up under $assignment, because it is pointing at that same Object instance.
<?php
$objectVar->foo = "qux";
print_r( $objectVar );
print_r( $reference );
print_r( $assignment );
//
// $objectVar --->+---------+
// |(handle1)----+
// $reference --->+---------+ |
// |
// +---------+ |
// $assignment -->|(handle1)----+
// +---------+ |
// |
// v
// Object(1):foo="qux"
//
?>
But it is not exactly the same as a reference. If you null out $objectVar, you replace the handle in its data slot with NULL. This means that $reference, which points at the same data slot, will also be NULL. But $assignment, which is a different data slot, will still hold its copy of the handle to the Object instance, so it will not be NULL.
<?php
$objectVar = null;
print_r($objectVar);
print_r($reference);
print_r($assignment);
//
// $objectVar --->+---------+
// | NULL |
// $reference --->+---------+
//
// +---------+
// $assignment -->|(handle1)----+
// +---------+ |
// |
// v
// Object(1):foo="qux"
?>
10-Oct-2007 05:41
The following odd behavior happens in php version 5.1.4 (and presumably some other versions) that does not happen in php version 5.2.1 (and possibly other versions > 5.1.4).
<?php
$_SESSION['instance']=...;
$instance=new SomeClass;
?>
The second line will not only create the $instance object successfully, it will also modify the value of $_SESSION['instance']!
The workaround I arrived at, after trial and error, was to avoid using object names which match a $_SESSION array key.
This is not intended to be a bug report, since it was apparently fixed by version 5.2.1, so it's just a workaround suggestion.
10-Aug-2007 02:06
referring to steven's post:
****
Perhaps this is because =& statements join the 2 variable names in the symbol table, whereas = statements applied to objects simply create a new independent entry in the symbol table that simply points to the same location as other entries. I don't know for sure - I don't think this behavior is documented in the PHP manual, so perhaps somebody with more knowledge of PHP's internals can clarify what is going on.
****
lets talk about
a =& b;
b = c;
PHP internally marks a to be a reference to b. If You reassign b PHP does not update a. But if you access a once more PHP looks at the current value of b (now containing c).
Both statements (a=b and a=&b) seem to do the same but they don't. However this changed for objects from PHP4 to PHP5. Where PHP4 needed this operator to avoid object cloning, PHP5 does not need it.
It is explained in chapter 21 (References Explained). It's important to understand that a becomes a reference and the following code will not modify b:
a =& b;
a =& c;
27-Oct-2006 07:00
If E_STRICT is enabled, the first example will generate the following error (and a few others akin to it):
Non-static method A::foo() should not be called statically on line 26
The example should have explicitly declared the methods foo() and bar() as static:
class A
{
static function foo()
{
...
