![]() |
|
|||||||
| Newsgroup de.comp.lang.php.misc Sonstige Fragen zu Anwendung und Programmierung. |
![]() |
|
|
Themen-Optionen | Ansicht |
|
#11
|
|||
|
|||
|
Stefan Froehlich schrieb:
> Na, dann macht man halt: > > | $h_obj = cHauptklasse::getInstance(); > | $u_obj = new cUnterklasse($h_obj, 1234); > > ...und schon hat man wieder ein Objekt ausserhalb der Hauptklasse > erzeugt. > Nicht, wenn Du eine Prüfung im Konstruktor der Unterklasse hast, schematisch so: class cUnterklasse { public function __construct(cHauptklasse $c) { if (!$c->isAllowedUnterklasse($this)) { throw new Exception('...'); } } } Damit kannst du dann eine Art "Multiton" in Abhängigkeit der Oberklasse realisieren. Im Fall der Fälle setzt Du den Konstruktor noch auf "final", und der Erbfall ist auch gesichert. HTH, Benjamin |
|
|
||||
|
||||
|
|
|
#12
|
|||
|
|||
|
Markus Malkusch wrote:
> Andreas Born: > >> Ich einigen Sprachen ist es mittlerweile üblich, auf öffentliche >> Eigenschaften nur mittels Getter und Setter zuzugreifen, auf diese >> Weise kann man bestimmen, ob eine Eigenschaft nur lesbar, nur >> schreibbar, oder beides ist. > > Hä? Keiner hindert Dich daran das in PHP genauso zu handhaben. Naja, es gibt keine echten Getter und Setter in PHP. Nur Hilfskontrukte über Funktionen oder eben __get() und __set(). > Ich mache das auch noch in Zeiten von __get() und __set() genauso. Ein > Attribut als public zu deklarieren kommt mir nicht in die Tüte. > >> In PHP ist dies nur mittels "Overloading" möglich. > > Ich versteh g'rad nicht was Überladung damit zu tun haben soll. Die PHP-Doku bezeichnet __get() und __set() als "Member Overloading", was m.E. der falsche Ausdruck dafür ist. Das schrieb ich ja auch. >> Der Wert einer Readonly-Eigenschaft wird in der Regel bei der >> Objekterstellung festgelegt. > > [..] > >> Sobald es sich bei $member aber um eine Objektinstanz mit eigenen >> readonly-Eigenschaften handelt, würde die Möglichkeit, $member von >> außen erstellen zu können, den readonly-Schutz konterkarieren. > > Das sehe ich nicht so (oder wir verstehen uns falsch). Es geht Dir > doch um den unveränderlichen Zustand eines Objektgraphen. Auch, aber nicht nur. (s.u.) > Der soll sobald Du das Wurzelobjekt erstellt hast feststehen. Genau. Und dieses Wurzelobjekt soll das einzige Objekt sein, das diesen Graphen erstellen darf.. > Wenn Du danach also außerhalb dieses Graphen irgendwelche Teilobjekte > erstellst, interessiert es den Graphen herzlich wenig, da Du (wegen > fehlenden Settern) keine Möglichkeit hast da irgendwas auszutauschen. > > Also als konkretes Beispiel: [...] Okay, den Graphen selber interessiert es nicht, richtig. Das habe ich auch bereits im Griff. Es geht mir darum, daß eben diese Teilobjekte nicht von außerhalb des Wurzelobjektes erstellbar sein sollten. Schematisch: Angenommen, ein solches Teilobjekt stellt einen Datensatz dar und bietet die Möglichkeit an, diesen Datensatz zu ändern oder zu löschen. Das Wurzelobjekt stellt nun eine Aufzählung solcher Datensätze bereit, inklusiver der Information ob dieser gelöscht werden darf. Den Benutzer braucht das nicht zu interessieren, denn er kann ja einfach das Teilobjekt des Graphen selbst erstellen und dann jeden beliebigen Datensatz löschen. Das Teilobjekt selbst ist nicht in der Lage festzustellen, ob die repräsentierte Datei gelöscht werden darf. Das genau legt das Wurzelobjekt fest. Aber vielleicht ist es eine Frage des Designs, daß man bestimmte Funktionalitäten einfach nicht in Objekte legen darf, die von außen erstellbar sind. Macht die Sache aber unleserlicher: Beabsichtigt: $graph = new graph(); $graph->getChild($id)->delete(); Problem: (das soll nicht möglich sein) $child = new child($id); $child->delete(); Besser (?) $graph = new graph(); $graph->deleteChild($graph->getChild()); Nun könnte es sich bei den Childs aber um verschiedene Objekttypen handeln, die gemeinsam haben, daß sie alle ein bestimmtes Interface implementieren, durch das z.B. die Methode delete() vorgegeben wird. Gegen die zweite Variante spricht also, daß das Wurzelobjekt u.u. garnicht weiß, wie das Childobjekt zu löschen ist. Möglichkeiten gibts ne Menge, das zu lösen. Aber anscheinend ist es vom Design her recht untypisch. Eine variante mittels protected: interface IDelete { public function delete(); protected function __construct($id,$deletable); } abstract class cPrototype { protected function createChild($className, $id, $deletable) { return new $className($id, $deletable); } } class cWurzel extends cPrototype { private $childs; public function getChild($id) { reutrn $this->childs[$id]; } public __construct() { $this->childs = array(); #.... füttern $this->childs['bsp'] = self::createChild('cChildA','bsp',true); $this->childs['exp'] = self::createChild('cChildB','exp',true); } } class cChildA extends cPrototype implements IDelete { private $id = null; private $deletable = false; protected function __construct($id, $deletable) { $this->id = $id; $this->deletable = $deletable; } public function delete() { if ($this->deletable) { # löschen... } else trigger_error('not allowed', E_USER_ERROR); } } class cChildB extends cPrototype implements IDelete { /* similar */ } Viele Grüße, Andreas |
|
#13
|
|||
|
|||
|
Andreas Born schrieb:
> Naja, es gibt keine echten Getter und Setter in PHP. Wie bitte? > Nur Hilfskontrukte > über Funktionen oder eben __get() und __set(). Kann ich nicht nachvollziehen. Meine Klassen haben ganz normale get- und set-Methoden, keine "Hilfskonstrukte über Funktionen" (was immer Du damit meinst), kein __get() oder __set(). Gruß. Claus |
|
#14
|
|||
|
|||
|
Claus Reibenstein wrote:
> Andreas Born schrieb: > >> Naja, es gibt keine echten Getter und Setter in PHP. > > Wie bitte? > >> Nur Hilfskontrukte über Funktionen oder eben __get() und __set(). > > Kann ich nicht nachvollziehen. Meine Klassen haben ganz normale get- > und set-Methoden, keine "Hilfskonstrukte über Funktionen" (was immer > Du damit meinst), kein __get() oder __set(). Deine set-Methode ist (vermutlich) nichts anderes als eine normale Funktion. class cObject { private $property; public function setProperty($value) { $this->property = $value } public function getProperty() { return $this->property; } } $object = new cObject(); $object->setProperty('hallo welt'); echo $object->getProperty(); Ein echter Setter wäre zwar auch eine (interne) Methode, die aber durch eine Zuweisung aufgerufen wird. Schematisch, weil es in php das eben *nicht* gibt; class cObject { private $property; public set property($value) { $this->property = $value } public get property() { return $this->property; } } $object = new cObject(); $object->property = 'hallo welt'; echo $object->property; Das ist realisierbar, aber eben nur mittels __get() und __set(). Ich unterscheide grunsdätzlich zwischen methoden und eigenschaften. Eine Methode wird wie eine funktion aufgerufen [$obj->method()] während eine Eigenschaft wie eine Variable verwendet wird [$obj->property = ...]. Natürlich steht es jedem frei, nur mit Funktionen zu arbeiten und ggf. anhand eines vorangestellten "get" oder "set" getter- und setter-funktionalität optisch davon abzugrenzen, aber echte Getter und Setter sind das in meinen Augen nicht. Ein Setter ist meiner Auffassung nach eine interne Methode, deren Aufruf durch eine Variablenzuweisung erfolgt, entsprechend wird ein Getter durch den lesenden Zugriff auf die Variable ausgelöst. Getter und Setter sind nicht extern aufrufbar und grenzen sich dadurch von normalen Funktionen ab. Ansonsten könnte man es auch einfach "Funktion" oder "Methode" nennen. ;-) Viele Grüße, Andreas |
|
#15
|
|||
|
|||
|
Andreas Born schrieb:
> Ich unterscheide grunsdätzlich zwischen methoden und eigenschaften. Eine > Methode wird wie eine funktion aufgerufen [$obj->method()] während eine > Eigenschaft wie eine Variable verwendet wird [$obj->property = ...]. Ich mache diese Unterscheidung auch - alle Eigenschaften sind private oder maximal protected, falls ich doch mal den Rückschritt zur Vererbung mache. > Natürlich steht es jedem frei, nur mit Funktionen zu arbeiten und ggf. > anhand eines vorangestellten "get" oder "set" getter- und > setter-funktionalität optisch davon abzugrenzen, aber echte Getter und > Setter sind das in meinen Augen nicht. Mag sein, dass das auf einer theoretischen Ebene keine Getter oder Setter sind - in PHP aber sind getX()- und setX()-Methoden genau das, was man Getter und Setter nennt. > Ein Setter ist meiner Auffassung nach eine interne Methode, deren Aufruf > durch eine Variablenzuweisung erfolgt, entsprechend wird ein Getter > durch den lesenden Zugriff auf die Variable ausgelöst. Getter und Setter > sind nicht extern aufrufbar und grenzen sich dadurch von normalen > Funktionen ab. Ansonsten könnte man es auch einfach "Funktion" oder > "Methode" nennen. ;-) Das kannst du mit __get() und __set() und ein wenig Reflection nachbilden. Allerdings halte ich das für unpraktisch (schlechten Stil), weil man einer Zuweisung nicht ansieht, dass der Wert verändert werden könnte. MfG Niels -- | http://www.kolleg.de · Das Portal der Kollegs in Deutschland | | http://www.bsds.de · BSDS Braczek Software- und DatenSysteme | | Webdesign · Webhosting · e-Commerce · Joomla! Content Management | ------------------------------------------------------------------ |
|
#16
|
|||
|
|||
|
Hallo,
Andreas Born schrieb am 16.11.2009 in de.comp.lang.php.misc: > Es geht mir darum, daß eben diese Teilobjekte nicht von außerhalb des > Wurzelobjektes erstellbar sein sollten. > Schematisch: Angenommen, ein solches Teilobjekt stellt einen Datensatz > dar und bietet die Möglichkeit an, diesen Datensatz zu ändern oder zu > löschen. Das Wurzelobjekt stellt nun eine Aufzählung solcher Datensätze > bereit, inklusiver der Information ob dieser gelöscht werden darf. Damit habe ich ein Problem. Für mich hat ein Objekt genau eine Aufgabe zu leisten, unabhängig vom der "Einsatz-Umgebung". Wenn ein Objekt also eine Aufagbe (Löschen) ausführen soll, soll es sich ggf. die Info (Deletable) spätestens dafür in dem Moment besorgen können. > Den > Benutzer braucht das nicht zu interessieren, denn er kann ja einfach das > Teilobjekt des Graphen selbst erstellen und dann jeden beliebigen > Datensatz löschen. Das Teilobjekt selbst ist nicht in der Lage > festzustellen, ob die repräsentierte Datei gelöscht werden darf. Das > genau legt das Wurzelobjekt fest. Dann würde ich das trotzdem durch Injection lösen. Die Idee: Das Child kann nur durch Rückfrage beim Owner herausfinden, ob es löschbar ist. Selbst wenn ein Child "losgelöst" erstellt wird, muss ein dabei angegebener Owner die Deletable-Frage mit FALSE beantworten, da ein Child NUR durch __construct Mitglied einer Wurzel werden kann und auch KEINE andere Wurzel dieses Child enthalten kann. interface IDelete { public function delete(); protected function __construct(cPrototype $owner, $id); } abstract class cPrototype { // static for self:: protected static function createChild($className, $id) { return new $className($this, $id); } public function isDeletable() { return FALSE; } } class cWurzel extends cPrototype { private $childs; public function getChild($id) { reutrn $this->childs[$id]; } public __construct() { $this->childs = array(); #.... füttern $this->childs['bsp'] = self::createChild('cChildA','bsp'); $this->childs['exp'] = self::createChild('cChildB','exp'); } public function isDeletable($child) { $return = FALSE; // Child dieses Objektes? if (array_search($child, $this->childs)) { // Ermitteln des Status, der vorher im __construct // ja auch irgendwie ermittelt worden sein muss :-) } return $return; } } class cChildA extends cPrototype implements IDelete { private $id = null; private $owner = NULL; protected function __construct(cPrototype $owner, $id) { $this->owner = $owner; $this->id = $id; } public function delete() { if ($this->owner->isDeletable($this)) { # löschen... } else trigger_error('not allowed', E_USER_ERROR); } } Knut -- http://es-f.com Web frontend for esniper, the console application for sniping eBay auctions. |
|
#17
|
|||
|
|||
|
Andreas Born schrieb:
> Claus Reibenstein wrote: > >> Andreas Born schrieb: >> >>> Naja, es gibt keine echten Getter und Setter in PHP. >> >> Wie bitte? >> >>> Nur Hilfskontrukte über Funktionen oder eben __get() und __set(). >> >> Kann ich nicht nachvollziehen. Meine Klassen haben ganz normale get- >> und set-Methoden, keine "Hilfskonstrukte über Funktionen" (was immer >> Du damit meinst), kein __get() oder __set(). > > Deine set-Methode ist (vermutlich) nichts anderes als eine normale > Funktion. > > class cObject { > private $property; > public function setProperty($value) { $this->property = $value } > public function getProperty() { return $this->property; } > } Solche Funktionen heißen Methoden. Getter und Setter _sind_ Methoden und sind genau so definiert. Eine andere Definition ist mir nicht bekannt. > $object = new cObject(); > $object->setProperty('hallo welt'); > echo $object->getProperty(); Das ist der übliche Weg. > Ein echter Setter wäre zwar auch eine (interne) Methode, die aber durch > eine Zuweisung aufgerufen wird. Schematisch, weil es in php das eben > *nicht* gibt; > > class cObject { > private $property; > public set property($value) { $this->property = $value } > public get property() { return $this->property; } > } > $object = new cObject(); > $object->property = 'hallo welt'; > echo $object->property; Hier allerdings bekomme ich Bauchschmerzen. Diese Zuweisung sieht aus wie eine direkte Zuweisung an eine Eigenschaft, ist aber keine. So etwas behagt mir gar nicht. Welche (mir offensichtlich unbekannte) OO-Sprache realisiert das so? PHP nicht, das wissen wir schon. Java und C++ auch nicht. In C++ kann man zwar per Operator Overloading so etwas Ähnliches basteln, aber als Setter würde ich das trotzdem nicht bezeichnen. > Ich unterscheide grunsdätzlich zwischen methoden und eigenschaften. Eine > Methode wird wie eine funktion aufgerufen [$obj->method()] während eine > Eigenschaft wie eine Variable verwendet wird [$obj->property = ...]. Genau das ist der Punkt: Getter und Setter sind Methoden und werden auch genau so aufgerufen. Eigenschaften, die direkt verändert werden können (was man normalerweise vermeiden sollte), werden per Zuweisung direkt geändert. Eine Anweisung, die wie eine normale Zuweisung aussieht, aber keine ist, sondern intern einen Setter aufruft, ist mir jedoch mehr als suspekt, da man ihr ihre tatsächlichen Eigenschaften nicht mehr ansieht. Welchen Wert hat eigentlich Deine Pseudo-Zuweisung? Nach Deinem schematischen Beispiel keinen, da kein return-Wert angegeben ist, womit Mehrfach-Zuweisungen im Stile von $obj1->x = $obj2->y = $obj3->z = ... schon mal nicht möglich sind :-) Gut, das lässt sich noch hinbiegen, indem man den Settern einen entsprechenden return-Wert verpasst. Meine Setter hingegen liefern idR eine Referenz auf das Objekt zurück (oder null, falls etwas schief läuft). Damit sind so hübsche Konstuktionen möglich wie $obj -> setx(...) -> sety(...) -> setz(...); Wie realisiere ich so etwas mit Deiner Pseudo-Zuweisung? > Natürlich steht es jedem frei, nur mit Funktionen zu arbeiten und ggf. > anhand eines vorangestellten "get" oder "set" getter- und > setter-funktionalität optisch davon abzugrenzen, aber echte Getter und > Setter sind das in meinen Augen nicht. In diesem Punkt haben wir offensichtlich gänzlich unterschiedlichen Ansichten. Gruß. Claus |
|
#18
|
|||
|
|||
|
Claus Reibenstein schrieb:
> Welche (mir offensichtlich unbekannte) OO-Sprache realisiert das so? PHP > nicht, das wissen wir schon. Java und C++ auch nicht. C# und Ruby machen es so und das finde ich eine der Stärken dieser Sprachen. Man kann Eigenschaften einfach setzen und nutzen wie lokale Variablen des gleichen Datentyps auch und muss sich nicht durch die Methoden kämpfen. Dass ein public Zugriff vorgespielt wird ist kein Problem, denn ein Entwickler dieser Sprachen weiss in der Regel dass bei solchen Zugriffen Methoden im Hintergrund sein könnten. -- Mit freundlichen Grüßen, Christoph Herrmann http://dragonprojects.de/ |
|
#19
|
|||
|
|||
|
On Mon, 16 Nov 2009 10:46:27 Christoph Herrmann wrote:
> Claus Reibenstein schrieb: > > Welche (mir offensichtlich unbekannte) OO-Sprache realisiert das > > so? PHP nicht, das wissen wir schon. Java und C++ auch nicht. > C# und Ruby machen es so und das finde ich eine der Stärken dieser > Sprachen. Man kann Eigenschaften einfach setzen und nutzen wie > lokale Variablen des gleichen Datentyps auch Das ist, wie vieles, eine Geschmacksfrage. Wenn nach: | $obj->a = $a; | $a = $obj->a; in $a nicht mehr zwingend der selbe Wert enthalten sein muss, wie zuvor, dann empfinde ich das als irritierend. Bei Methoden rechne ich alleine durch ihre Syntax ganz grundsaetzlich damit. > Dass ein public Zugriff vorgespielt wird ist kein Problem, denn > ein Entwickler dieser Sprachen weiss in der Regel dass bei solchen > Zugriffen Methoden im Hintergrund sein könnten. Ich persoenlich finde halt, dass dann auch der Sinn der Sache verloren geht, naemlich die Unterscheidung zwischen Zuweisungen und Funktionsaufrufen. Es gibt dann nur noch "Aufrufe", hinter denen immer Methoden stecken (koennen), ob nun mit oder ohne Klammern. Servus, Stefan -- http://kontaktinser.at/ - die kostenlose Kontaktboerse fuer Oesterreich Offizieller Erstbesucher(TM) von mmeike Gelassen und doch gebissen?! Stefan - Trost in den Stunden des Zorns. (Sloganizer) |
|
#20
|
|||
|
|||
|
On Mon, 16 Nov 2009 10:08:16 Claus Reibenstein wrote:
> Welchen Wert hat eigentlich Deine Pseudo-Zuweisung? Nach Deinem > schematischen Beispiel keinen, da kein return-Wert angegeben ist, womit > Mehrfach-Zuweisungen im Stile von > > $obj1->x = $obj2->y = $obj3->z = ... > schon mal nicht möglich sind :-) > Gut, das lässt sich noch hinbiegen, indem man den Settern einen > entsprechenden return-Wert verpasst. Das wird man im Regelfall wohl auch tun, so wie Du selbst ja auch: > Meine Setter hingegen liefern idR eine Referenz auf das Objekt zurück > (oder null, falls etwas schief läuft). ....die entsprechenden Konventionen befolgst. Aber gerade das macht IMHO deutlich, dass sich die beiden Zugriffsarten primaer durch ihre Syntax unterscheiden: Ich kann Methoden schreiben, die Properties abbilden, und ich kann mit dem Zugriff auf Properties Methoden aufrufen. Eventuell war es ja von Anfang an ein Fehler, die Konzepte "Variable" und "Funktion" einfach so 1:1 auf Objekte zu uebertragen, wenn man sie dort dann (beinahe - das gilt natuerlich nicht mehr fuer Methoden mit mehr als einem Argument) bis zur Ununterscheidbarkeit aufweicht. Servus, Stefan -- http://kontaktinser.at/ - die kostenlose Kontaktboerse fuer Oesterreich Offizieller Erstbesucher(TM) von mmeike Erfrischend natürlich - Stefan: waschen, welch warmes Verlangen! (Sloganizer) |
|
|
|
|
![]() |
| Themen-Optionen | |
| Ansicht | |
|
|
Ähnliche Themen
|
||||
| Thema | Erstellt von | Forum | Antworten | Letzter Beitrag |
| Designfrage | Konrad Schiemert | Newsgroup microsoft.public.de.vc | 2 | 11-11-2009 11:00 AM |
| Designfrage | Bernhard | Newsgroup microsoft.public.de.german.entwickler.dotnet.asp | 2 | 03-26-2009 05:09 PM |
| Designfrage | Norbert Stellberg | Newsgroup de.comp.lang.delphi.misc | 29 | 02-10-2009 07:55 AM |
| Designfrage | Tobias Nissen | Newsgroup de.comp.os.unix.programming | 12 | 03-12-2008 06:55 PM |
| Designfrage | Uwe Ziegenhagen | Newsgroup de.comp.lang.java | 17 | 09-19-2007 12:26 PM |