• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

Problem mit OOP

freakXHTML

Mitglied
Hallo zusammen,
warum wird hier nicht 5 ausgegeben?
PHP:
<?php
class Beispiel
{
private $zahl = 0;
function _construct($parm)
{
$zahl = $param;
}
public function get_zahl()
{
return $zahl;
}
}
 
$exmp = new Beispiel(5);
echo $exmp->get_zahl();
?>

Vielen Dank
lg, freakXHTML
 
Du hast dich zum einem bei $param verschrieben (einmal parm und einmal param). Zudem musst du innerhalb der Klasse mit $this->variable auf Variablen zugreifen.
Verbessert:
PHP:
<?php
class Beispiel
{
private $zahl = 0;
function __construct($param)
{
$this->zahl = $param;
}
public function get_zahl()
{
return $this->zahl;
}
}
 
$exmp = new Beispiel(5);
echo $exmp->get_zahl();
?>

Edit: Und du hast _construct anstatt __construct geschrieben.

Edit 2: :D war schneller.^^
 
Edit: Bah, doppelt. ;)

Da sind ein paar Tippfehler drin ("__construct" (zwei Unterstriche), "$parm") und Instanzvariablen muss $this-> vorangestellt werden.

Mehr hier: PHP: Die Grundlagen - Manual

PHP:
<?php

class Beispiel
{
    // Statt private würde ich protected nehmen
    private $zahl = 0;

    public function __construct($param)
    {
        $this->zahl = $param;
    }

    public function get_zahl()
    {
        return $this->zahl;
    }
}

$exmp = new Beispiel(5);
echo $exmp->get_zahl();
 
Hi,
oh man...ich bin auch doof! Tja...ich habe den Wald vor lauter Bäumen nicht gesehen ;). Ich programmiere eigentlich in C++ und verstehe nicht, warum $this obligatorisch ist. Außerdem ist mir nicht klar, was $this in PHP ist. Normalerweise handelt es sich dabei um einen Zeiger auf das Objekt, welches z.B. eine Methode ausgeführt hat. Doch in PHP gibt es doch gar keine Zeiger. Wie funktioniert das also hier?

Vielen Dank
lg, freakXHTML
 
Ich kenne mich wiederum nicht mit C++ aus, bei Java ist es aber ähnlich:

$zahl ist ein Attribut der Klasse (und somit auch aller Objekte der Klasse Beispiel). Im Konstruktor soll jetzt das Attribut verändert werden. Mit $this-> (in Java this. ) sagst du explizit, dass ein Attribut verändert werden soll. $this-> ist quasi ein Objekt, das immer auf sich selbst zeigt. $exmp->get_zahl(); holt sich den Wert von get_zahl(). get_zahl() returnt einfach nur $this->zahl. $this-> ist in diesem Fall wieder die Selbstreferenz des Objektes.

Klarer wird es vielleicht auch hier:
Code:
public function __construct($zahl)
{
    $this->zahl = $zahl;
}

Würdest du hier einfach nur $zahl = $zahl schreiben, käme wahrscheinlich ein Fehler, denn woher soll denn der Compiler wissen, welches $zahl gemeint ist? Löst man das ganze mit einer Selbsreferenz ist es kein Problem mehr.

Hoffe es stimmt in etwa so, so ist es zumindest in Java, in PHP hab ich noch nie Objektorientiert bearbeitet.
 
freakXHTML schrieb:
verstehe nicht, warum $this obligatorisch ist

Das ist letztlich einfach in der Syntax so festgelegt. Wenn ich raten sollte: Vermutlich macht es die Auswertung im PHP-Interpreter leichter und damit schneller, weil nicht festgestellt werden muss, ob eine Variable, die in einer Methode eins Objekts verwendet wird, auch in der Symboltabelle der Klasseninstanz auftaucht. Das fällt bei mehr oder weniger kompilierten Programmen (C++, Java, ...) nicht ins Gewicht, bei "reinen" Interpretersprachen wie PHP aber schon.

Doch in PHP gibt es doch gar keine Zeiger. Wie funktioniert das also hier?

Dazu steht auch etwas auf der Seite, die ich dir verlinkt habe.

PHP-Handbuch schrieb:
$this ist eine Referenz auf das aufrufende Objekt [...]

Weitere Informationen zu Referenzen: http://php.net/manual/de/language.references.php

Tar schrieb:
bei Java ist es aber ähnlich

Kleinigkeit: Bei Java ist es eher wie bei C++. "this." muss nicht zwingend gesetzt werden, wenn Verwechslungsgefahr ausgeschlossen ist.

Würdest du hier einfach nur $zahl = $zahl schreiben, käme wahrscheinlich ein Fehler, denn woher soll denn der Compiler wissen, welches $zahl gemeint ist?

Damit ist eindeutig die Variable $zahl innerhalb der Methode gemeint. Das wäre auch in Java so. Dort müsstest du in diesem Fall

Code:
this.zahl = zahl;

schreiben, wenn du den Wert der "Funktionsvariable" zahl der Instanzvariable zahl zuweisen möchtest.
 
Zuletzt bearbeitet:
Ah ok! Vielen Dank. Ich habe noch eine andere Frage. Warum gibt das Folgende keinen Fehler? Eigentlich dürfte doch "$zahl" nicht mitvererbt werden, da es unter private steht. Es müsste doch eigentlich "protected" sein. Es dürfte also keine Ausgabe erfolgen oder ein Fehler hätte vielleicht sogar kommen müssen. Es funktioniert jedoch und ich weiß nicht warum:

PHP:
<?php
class Beispiel
{
private $zahl = 0;
function __construct ($param)
{
$this->zahl = $param;
}
public function __invoke()
{
return $this->zahl;
}
}

class foo extends Beispiel
{
}

$examp = new foo(8);
echo $examp();
?>

Vielen Dank
lg, freakXHTML
 
Einfach gesagt: Du kannst im Code von foo nicht per $this->zahl auf die Instanzvariable zugreifen, in Beispiel jedoch schon. Das besagt private: Zugriff nur von der Klasse aus möglich, in der die Variable definiert wurde.

- PHP: Sichtbarkeit - Manual

PHP:
class Beispiel
{
    private $zahl = 0;

    public function __construct($param) {
        $this->zahl = $param;
    }

    public function __invoke() {
        return $this->zahl;
    }
}

class foo extends Beispiel
{
    public function getZahl()
    {
        return $this->zahl;
        // Notice: Undefined property: foo::$zahl in /home/marc/w/nb/bub.php  on line 20
    }
}

error_reporting(-1); // Alle Fehler anzeigen

$examp = new foo(8);
echo $examp();

echo $examp->getZahl();
 
Achso. Das ist natürlich einleuchtend. Ich habe noch eine letzte Frage. Diese bezieht sich auf abstrakte Methoden.

1.) Wenn eine Methode abstrakt sein soll, muss dann auch die zugehörige Klasse abstrakt sein? Eigentlich schon, oder?

2.) Was bringt überhaupt eine abstrakte Methdode. In der einen Klasse deklariere ich sie, aber implementiere sie nicht. Dann erstelle ich eine Kindklasse und implementiere die Methode dort. Dann kann ich doch gleich in der Kindklassse auch die Deklaration vornehmen:

PHP:
<?php
abstract class Eltern
{
private $var;
function __construct($param)
{
$this->var = $param;
}
public function get_var()
{
return $this->var;
}
abstract public function give_hallo();
}
 
class Kind extends Eltern
{
public function give_hallo() //was bringt es, dass diese abstrake Methode geerbt wird? Ich kann sie doch gleich hier deklarieren
{
echo "Hallo";
}
}
 
$foo = new Kind(4);
echo $foo->give_hallo();
?>
`

Vielen Dank
lg, freakXHTML
 
abstrakte Methoden und Klassen sind eigentlich nur in Java oder C++ notwendig. Da du damit Adapter u.ä. erschaffen kannst und du beim kompilieren keine Fehler bekommst. In Skriptsprachen sind sie eigentlich unnötig.
 
Ich frage mich sowieso, ob OOP in PHP häufig genutzt wird. Ich stelle mir PHP nie als riesen Programm vor, sonder eher wie viele kleine Scripts. Stimmt das?

Viele Grüße
freakXHTML
 
Ich frage mich sowieso, ob OOP in PHP häufig genutzt wird. Ich stelle mir PHP nie als riesen Programm vor, sonder eher wie viele kleine Scripts. Stimmt das?

Viele Grüße
freakXHTML

Es kommt immer drauf an was man entwickelt.
Ich hab schon Klassen mit etwa 700 Zeilen (ca 25 Methoden + Getter und Setter) geschrieben.
Zur Zeit screibe ich an einem Browsergame. Da wäre man ohne OOP verloren, da man sehr viele Schnittstellen hier hat.
Außerdem ist OOP ja wegen dem eigenen Namespace eine schöne Sache, sodass man die Klassen in anderen Projekten verwenden kann, ohne auf Konflikte zu stoßen
 
Das kommt auf den Umfang des Projektes an und auf die Fähigkeiten des Programmierers. Ich z.B. arbeite nur objektorientiert mit PHP, erstelle mir Klassen die die benötigten Funktionen bereitstellen, so kann man die Klasse einfach in ein neues Projekt übernehmen und sofort nutzen. Die Funktionalität ist so auch gut getrennt vom Rest des Projektes.
 
Ok, vielen Dank für die Hinweise. Dass Browergames wohl mit OOP arbeiten, ist eigentlich klar, da diese bereits komplexer sind. Mir ist aber dennoch noch eine andere Frage eingefallen (war doch nicht die letzte ;)). Ich möchte über ein Eingabefeld den Namen einer Variable eingeben, in die dann ein Wert geschrieben wird. Hier stehen die Variablen $var1, $var2 und $var3 zur Verfügung. Falls die eingegebene Variable nicht vorhanden ist, so soll eine Fehlermeldung erscheinen. Meine Lösung klappt aber nicht:

PHP:
<?php
class Write_Val
{
private $val1, $val2, $val3;
public function set_value($val,$wert)
{
return $this->val = $wert; //Das geht wohl nicht. Aber wie muss ich hier verbessern?
}
public function __set($a,$v)
{
echo "$a mit $v ist nicht vorhanden"; //Es wird immer die __set Methode aufgerufen :(
}
 
}
$foo = new Write_Val();
$foo->set_value($_POST['attr'], $_POST['wert']);
?>

Vielen Dank
lg, freakXHTML
 
Du gibst $this->val zurück, hast aber nur die Variablen val1, val2 und val3. Entweder erweiterst du $this->val um 1, 2 oder 3, oder um den übergebenen Wert val anzusprechen entfernst du $this.
 
Ich frage mich sowieso, ob OOP in PHP häufig genutzt wird. Ich stelle mir PHP nie als riesen Programm vor, sonder eher wie viele kleine Scripts. Stimmt das?
Ja, aber das hat nichts mit OOP oder nicht zu tun. Du kannst Klassen auch ohne Probleme zur Laufzeit nachladen in PHP.
 
Zuletzt bearbeitet von einem Moderator:
Struppi schrieb:
abstrakte Methoden und Klassen sind eigentlich nur in Java oder C++ notwendig. Da du damit Adapter u.ä. erschaffen kannst und du beim kompilieren keine Fehler bekommst. In Skriptsprachen sind sie eigentlich unnötig.

Das Adapter-Muster wird auch in PHP verwendet. Zum Beispiel für Datenbank-Klassen: http://framework.zend.com/code/brow...rd/trunk/library/Zend/Db/Adapter/Abstract.php

Die Idee hinter abstrakten Klassen ist es, bei einer Gruppe von Objekten mit nur punktuell abweichenden Aufgaben/Eigenschaften die gemeinsame Funktionalität in einer abstrakten Elternklasse zu implementieren und abweichende Funktionalität in den Kindklassen. Im Code kann dann mit Objekten vom Typ der abstrakten Klasse gearbeitet werden. Welche konkrete Implementation vorliegt, ist nicht relevant, da sichergestellt ist, dass auch Kindobjekte alle erwartete Funktionalität implementieren.

Das Beispiel funktioniert wohl nur im Firefox (wegen der speziellen CSS3-Regel mit Namespace):

PHP:
<?php

abstract class DrawingObject
{
    protected $_x           = 0;
    protected $_y           = 0;
    protected $_borderColor = 'ff0000';
    protected $_backgroundColor = 'ffffff';

    abstract public function draw();

    public function __construct()
    {
        $this->_x = rand(0, 400);
        $this->_y = rand(0, 400);
    }

    public function setBorderColor($newColor)
    {
        $this->_borderColor = $newColor;
    }

    public function getBorderColor()
    {
        return $this->_borderColor;
    }

    public function setBackgroundColor($newColor)
    {
        $this->_backgroundColor = $newColor;
    }

    public function getBackgroundColor()
    {
        return $this->_backgroundColor;
    }

    public function setPos($x, $y)
    {
        $this->_x = (int) $x;
        $this->_y = (int) $y;
    }

    public function getPos()
    {
        return array($this->_x, $this->_y);
    }
}

class Circle extends DrawingObject
{
    public function draw()
    {
        // Logik, Kreis zu zeichnen
        echo '<div style="
            text-align: center;
            background: #' . $this->_backgroundColor. ';
            line-height: 200px;
            position: absolute;
            top: ' . $this->_y . 'px;
            left: ' . $this->_x . 'px;
            border: 1px solid #' . $this->_borderColor. ';
            -moz-border-radius: 200px;
            width: 200px;
            height: 200px;
            ">Ich bin ein Kreis</div>';
    }
}

class Rectangle extends DrawingObject
{
    public function draw()
    {
        // Logik, Rechteck zu zeichnen
        echo '<div style="
            text-align: center;
            background: #' . $this->_backgroundColor. ';
            line-height: 100px;
            position: absolute;
            top: ' . $this->_y . 'px;
            left: ' . $this->_x . 'px;
            border: 1px solid #' . $this->_borderColor. ';
            width: 300px;
            height: 100px;
            ">Ich bin ein Rechteck</div>';
    }
}



class Scene
{
    protected $_drawingObjects = array();

    public function add(DrawingObject $do)
    {
        $this->_drawingObjects[] = $do;
    }

    public function render()
    {
        foreach ($this->_drawingObjects as $do) {
            $do->draw();
        }
    }
}



$scene = new Scene();

$scene->add(new Circle());

$c2 = new Circle();
$c2->setBorderColor('00ff00');
$c2->setBackgroundColor('eeffee');

$scene->add($c2);
$scene->add(new Circle());
$scene->add(new Rectangle());

$scene->render();

Edit: In PHP ist so ziemlich jedes OOP-Muster anwendbar und wird auch angewendet. Die Frage sollte generell eher lauten, ob sich ein Muster/welches Muster sich für einen Anwendungsfall eignet. Das sollte vom Prinzip her erstmal losgelöst von der konkreten Sprache betrachtet werden.
 
Zuletzt bearbeitet:
Naja, ich hab auch nicht gesagt das es nicht anwendbar ist, es ist aber überflüssig.

Im gegenteil es schränkt ein. Denn in Skriptsprachen kannst du zur Laufzeit ja alles machen, d.h. der konkrete Adapter kann im nächsten Moment wieder ein String sein und umgekehrt, genauso kannst du zur Laufzeit jede Funktion aufflanschen die du willst.

Ich denke das mit den abstrakten Klassen/Methoden bläht nur unnötig den Quellcode auf, was in übersetzten Sprachen egal ist. Aber bei Skriptsprachen u.U. (je nachdem wie die das optimieren) eine unnötige Bremse ist.
 
Bei OOP geht's wohl in erster Linie nicht um Performance, sondern um Übersichtlichkeit, bessere Wartbarkeit, einfache Erweiterbarkeit und Wiederverwendbarkeit von Programmen oder Programmteilen. Das selbe kann man selbstverständlich mit einem prozeduralen Programmierstil erreichen (hat man zu PHP4-Zeiten schließlich fast immer so gemacht) und ist für viele Fälle sogar die geeignetere Methode. Zu Zeiten, wo sich Webseiten "Application" nennen dürfen und immer mehr Funktionen bieten, spricht es eher dafür Objekt-Orientiert zu arbeiten. Das benutzte Entwurfsmuster richtet sich dabei an die Anwendung; dass schließt natürlich Abstrakte Klassen mit ein.

Die eventuelle Performence-Einbüße kann man mit einem Caching-System für Klassen/Daten und einem Memcache/APC für den von PHP erzeugten Bytecode entgegenwirken.
Und man unterscheidet bei Scriptsprachen auch zwischen Compile-Time und Run-Time (Laufzeit). Bei Facebook wird PHP-Code sogar in C++ und dann in Maschinencode übersetzt, was natürlich eval() etc. nicht mehr erlaubt.
 
Zurück
Oben