PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Problem mit PHP/OOP


Gast
2006-03-21, 15:40:32
Hallo zusammen,
ich habe hier ein kleines Problem mit einem PHP Code. Mache gerade erste Gehversuche in OOP. Folgender Code gibt immer nur den Wert aus, der zuletzt im Konstrucktor zugewiesen wird und ich weiß nicht warum.
Ich kann bei der echo Anweisung Variablen angeben wie ich will. Egal was, es kommt immer der Wert der letzten Zuweisung. Woran liegt das??

Code:

<?php
class Timer{
var $currentMonth;
var $currentDay;
var $daysOfMonth;
var $currentYear;
var $startDayOfMonth;

function Timer($timestamp){
$currentTime = getdate($timestamp);
$this -> $currentMonth = $currentTime["mon"];
$this -> $currentDay = $currentTime["mday"];
$this -> $currentYear = $currentTime["year"];

}
}

$myClass = new Timer(time());
echo $myClass -> $currentDay;


?>

Marscel
2006-03-21, 15:49:00
Ürks.

Erstmal, so macht man doch keine Code, jedenfalls würde der sich bei mir nicht einmal fehlerlos parsen lassen:

<?php

class Timer{
var $currentMonth;
var $currentDay;
var $daysOfMonth;
var $currentYear;
var $startDayOfMonth;

function Timer($timestamp){
$currentTime = getdate($timestamp);
$this->currentMonth = $currentTime["mon"];
$this->currentDay = $currentTime["mday"];
$this->currentYear = $currentTime["year"];
}
}

$myClass = new Timer(time());
echo $myClass->currentDay;

?>

Wo liegt das Problem? Du übergibts dem Konstuktor einen Timestamp und weist den einzelnen Elementen die Jahres-, Monats- und Tageszahl zu, anhand des Arrays, das getdate() zurückgeliefert hat.

Das, was hinter dem echo steht, greift auf den Tages-Integer der Klasse zu, und das ist nun einfach immer dasselbe bei dem Timestamp, heute ist der 21.03, d.h. du wirst heute noch so oft den Browser aktualisieren können, du wirst bis 23:59 "21" ausgegeben bekommen. Und bezogen auf Jahr und Monat wäre ja die Schlussfolgerung nun auch logisch...

Gast
2006-03-21, 15:59:48
Sorry wegen der Formatierung.

Ich war ja auch der Meinung, dass es da kein Problem gibt. Nur leider kam den ganzen Morgen nicht 21 raus sondern grundsätzlich irgendein anderer Mist. Naja, jetzt gehts auf jeden Fall. Alles komisch, aber trotzdem Danke!

Marscel
2006-03-21, 16:03:16
Sorry wegen der Formatierung.

Das war nicht das Problem, sondern dass du, um auf Elemente einer Klasse zuzugreifen:

$klasse -> $element;

geschrieben hast, das ist eigentlich ungültig, jedenfalls lässt sich das lokal nicht parsen (PHP5 + Strict Mode), das hat i.d.R. so auszusehen:

$klasse->element;

clm[k1]
2006-03-21, 16:27:43
Sauberer währe es außerdem auf die member-variablen nur per getter und setter zu zu greifen.

Wenn du PHP5 benutzt solltest du außerdem Gebrauch von Sichtbarkeitsoperatoren machen (private, protected, public) - Stichwort Kapselung. Das Schlüsselwort var ist in PHP5 AFAIK deprecated.


just my 2 cent
clm[k1]

Coda
2006-03-21, 16:29:22
']Sauberer währe es außerdem auf die member-variablen nur per getter und setter zu zu greifen.Dadurch wird die Kapselung auch nicht besser. Wenn einer Member-Variable sowohl Set- als auch Get-Funktionen hat zeugt das meistens von schlechtem Design.

Allgemein sollte man die Klassen die Operationen darauf möglichst selbst machen lassen, d.h. statt (C++) "cout << foo.GetBar() << std::endl;" lieber "foo.OutputBar();".

Aber eventuell hast du es ja auch so gemeint gehabt :)

clm[k1]
2006-03-21, 16:52:34
Aber eventuell hast du es ja auch so gemeint gehabt :)

Ja hatte ich, sorry wenn das falsch rüber kam.


Gruß
clm[k1]

Xmas
2006-03-21, 19:45:57
Dadurch wird die Kapselung auch nicht besser. Wenn einer Member-Variable sowohl Set- als auch Get-Funktionen hat zeugt das meistens von schlechtem Design.

Allgemein sollte man die Klassen die Operationen darauf möglichst selbst machen lassen, d.h. statt (C++) "cout << foo.GetBar() << std::endl;" lieber "foo.OutputBar();".
Das kann ich jetzt beides nicht nachvollziehen.

Marscel
2006-03-21, 20:18:30
Das kann ich jetzt beides nicht nachvollziehen.

Ich das auch nicht so ganz:

Allgemein sollte man die Klassen die Operationen darauf möglichst selbst machen lassen, d.h. statt (C++) "cout << foo.GetBar() << std::endl;" lieber "foo.OutputBar();".

Angenommen, GetBar() liefert den Wert der Elementvariablen bar von foo zurück, was ist daran (cout << foo.GetBar() << std::endl;) denn nicht so gut? Vielleicht ist das Beispiel nicht so gut, aber im Falle von OutputBar() bräuchte man doch immer noch eine Elementfunktion GetBar() für Funktionen, die nur am Wert, nicht am ostream interessiert sind, oder?

Ich selber versuche immer, so viel wie möglich von einander zu trennen, d.h. eine Berechnungsfunktion schreibt i.d.R nichts in die Konsole, sondern gibt einen Wert/Struct zurück, dass dann von der Funktion im Scope darüber weiterverarbeitet wird.

Coda
2006-03-22, 01:17:37
Das kann ich jetzt beides nicht nachvollziehen.Inwiefern? Was nützt einem ein private bei einer Membervariable, wenn ich sie trotzdem mit Set und Get verändern kann? - Ja ich weiß dass man eventuell noch was damit rumrechnen kann, aber dann sollten die Funktionen schon nicht mehr Get und Set heißen meiner Meinung nach.

Das Beispiel war etwas schlecht ja. Pure Getter sind meistens noch in Ordnung. Aber ich hab schon Code gesehen die Kapseln wirklich nur weil sie es so gelernt haben und stopfen dann alles mit Set und Get voll und machen im Endeffekt nichts anderes als das Zeug gleich in ne struct zu stopfen X-D

Bietchiebatchie
2006-03-22, 02:39:50
Inwiefern? Was nützt einem ein private bei einer Membervariable, wenn ich sie trotzdem mit Set und Get verändern kann? - Ja ich weiß dass man eventuell noch was damit rumrechnen kann, aber dann sollten die Funktionen schon nicht mehr Get und Set heißen meiner Meinung nach.

Das Beispiel war etwas schlecht ja. Pure Getter sind meistens noch in Ordnung. Aber ich hab schon Code gesehen die Kapseln wirklich nur weil sie es so gelernt haben und stopfen dann alles mit Set und Get voll und machen im Endeffekt nichts anderes als das Zeug gleich in ne struct zu stopfen X-D

Naja, ich sag mal es ist gewissermaßen sicherer und man kann einfacherer Dinge im Nachhinein ändern, wenn man immer setter und getter verwendet.

Beispiel(einfacher):
eine Klasse sammelt (aus irgendeinem Grund) Daten vom selbem Typ.
Anfangs denke ich, es reicht, wenn ich die Daten einfach in einer Liste speichere; später merke ich jedoch dass es sehr viele Daten werden und ich ersetzte die Liste durch eine Baumstruktur; falls die Liste public war, hab ich ein Problem. Existieren jedoch getter und setter funktionen, muss ich nur diese umschreiben, dass sie aus dem Baum nochmal eine Liste machen(bzw. aus der Liste einen Baum).

Beispiel(sicherer):
Ich hab eine simple Farbklasse RGB( mit drei int r,g,b natürlich) und später fällt mir auf dass ich sicherstellen will, dass dem Feld nur sinnvolle ( 0<= x <= 255 ) und keine unsinnigen Werte zugewiesen werden.

Natürlich merkt man beiden Beispielen an, dass ich mir sie grad ausgedacht hab ;) und man hätte beide Probleme auch im Vorfeld bedenken können, aber ich denke, es wird klar, warum es (fast) immer Sinn macht, getter und setter zu verwenden.
Nichtsdestotrotz hast du natürlich Recht, dass es schlechtes Design ist, jede private Variable public zu machen.

Xmas
2006-03-22, 14:32:54
Inwiefern? Was nützt einem ein private bei einer Membervariable, wenn ich sie trotzdem mit Set und Get verändern kann? - Ja ich weiß dass man eventuell noch was damit rumrechnen kann, aber dann sollten die Funktionen schon nicht mehr Get und Set heißen meiner Meinung nach.
Dem kann ich mich jetzt nicht anschließen. Die Namen sollten nach ihrer nach außen wahrgenommenen Funktion gewählt werden und die Implementation komplett verstecken. Und bei einem Label-Widget mit Autosize erwartest du wohl auch, dass SetText() die Größe ändert.
Interfaces bestehen ja nicht umsonst ausschließlich aus Methoden.
Dazu kommt dass ein Setter validieren kann, was bei public Membervariablen natürlich nicht geht.

Bei Gettern und Settern spielt es natürlich auch eine Rolle welche Sprache man verwendet. In C# kann man häufig genausogut Properties verwenden, in Python ist sowieso alles public, usw. Und in derselben Kompilierungseinheit macht der Compiler eh Inlining.


Das Beispiel war etwas schlecht ja. Pure Getter sind meistens noch in Ordnung. Aber ich hab schon Code gesehen die Kapseln wirklich nur weil sie es so gelernt haben und stopfen dann alles mit Set und Get voll und machen im Endeffekt nichts anderes als das Zeug gleich in ne struct zu stopfen X-D
Immerhin kann man so später problemlos die Implementation vollkommen umkrempeln.

The_Invisible
2006-03-22, 15:22:45
für OOP in PHP würde ich sowieso PHP5 empfehlen.

siehe: http://de.php.net/manual/de/language.oop5.php

PHP5 bringt gerade für OOP viele neue Sachen mit

mfg