[PHP4] Object trashen; hoe mogelijk?

Pagina: 1
Acties:

  • Spider.007
  • Registratie: December 2000
  • Niet online

Spider.007

* Tetragrammaton

Topicstarter
Ik heb een lastig probleem wat ik heb weten te herleiden tot de volgende [voorbeeld] code:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?PHP
$x = new x();

class x {
        function x(){
                echo "x:x1\n";
                $this->z = new a($this);
                $this->z->init();
                echo "x:x2\n";
        }

        function r(){
                echo "x:r1\n";
                $this->z->destroy();
                $this->z = new b($this);
                echo "x:r2\n";
        }
}

class a {
        function a(&$x){
                $this->x =& $x;
                echo "\ta:a\n";
        }

        function init(){
                echo "\ta:i1\n";
                $this->x->r();
                echo "\ta:i2\n";
        }

        function destroy(){
                echo "\ta:d1\n";
                settype(&$this, 'null');
                echo "\ta:d2\n";
        }
}

class b {
        function b(){
                echo "\tb:b\n";
        }
}
de output hiervan is:
code:
1
2
3
4
5
6
7
8
9
10
x:x1
        a:a
        a:i1
x:r1
        a:d1
        a:d2
        b:b
x:r2
        a:i2
x:x2

Het probleem is dat de x->r() gebruikt wordt om het x->z object te herinstantieren. x->z is allereerst een instantie van Class a; en na x->r() een instantie van Class b. Mijn probleem zit hem in het feit dat na $this->x->r(); toch echo "\ta:i2\n"; wordt uitgevoerd; ondanks dat $this->z = new b($this); x->z overschrijft. Is dit een fout in mijn denkwijze; mijn code; of een beperking waar ik niet omheen ga komen? Het unsetten van x->z werkt overigens niet; net zoals het hier gesuggereerde settype(&$this, 'null');. Heeft er hier iemand een idee hoe ik ik kan voorkomen dat a->init verder wordt uitgevoerd nadat deze zichzelf overschreven / verwijderd heeft?

Is de enige oplossing hiervoor echt het returnen uit a->init indien $this->x->r() succesvol is uitgevoerd?

---
Prozium - The great nepenthe. Opiate of our masses. Glue of our great society. Salve and salvation, it has delivered us from pathos, from sorrow, the deepest chasms of melancholy and hate


Verwijderd

Er is niets dat de code executie tussen $this->x->r(); en echo "\ta:i2\n"; zou kunnen stopzetten. Je moet dus inderdaad ergens een return statement gaan gebruiken. Je mag niet verwachten dat omdat je een object vervangt of verwijdert, die code niet meer uitgevoerd gaat worden. Die code is al geparset.

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 00:07

Creepy

Tactical Espionage Splatterer

Ik kan me voorstellen dat terwijl z->init() nog uitgevoerd wordt je z niet zomaar kan destroyen en dat in dit geval z->init() gewoon uitgevoerd blijft worden. Pas nadat het geheel is uitgevoerd is er geen regerentie meer naar z en kan het overschreven worden.

Waarom wil je dit eigenlijk doen? In deze vorm komt het nogal vreemd op me over.

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • Spider.007
  • Registratie: December 2000
  • Niet online

Spider.007

* Tetragrammaton

Topicstarter
Verwijderd schreef op zaterdag 19 augustus 2006 @ 16:10:
Er is niets dat de code executie tussen $this->x->r(); en echo "\ta:i2\n"; zou kunnen stopzetten. Je moet dus inderdaad ergens een return statement gaan gebruiken. Je mag niet verwachten dat omdat je een object vervangt of verwijdert, die code niet meer uitgevoerd gaat worden. Die code is al geparset.
Het vervelende is dat niet alleen een echo-statement wordt uitgevoerd; maar ook alle andere code in de methode. Een $this->do(); wordt bijvoorbeeld ook gewoon uitgevoerd. Ik zou verwachten dat de code niet meer werd uitgevoerd aangezien het object niet meer zou moeten bestaan.
Creepy schreef op zaterdag 19 augustus 2006 @ 16:11:
Ik kan me voorstellen dat terwijl z->init() nog uitgevoerd wordt je z niet zomaar kan destroyen en dat in dit geval z->init() gewoon uitgevoerd blijft worden. Pas nadat het geheel is uitgevoerd is er geen regerentie meer naar z en kan het overschreven worden.
Het overschrijven gaat zonder problemen; en verder calls naar x->z worden ook gewoon goed naar b toegeleid. Code die echter al geparsed is wordt niet afgesloten of gestopt; iets wat ik wel verwacht had.
Waarom wil je dit eigenlijk doen? In deze vorm komt het nogal vreemd op me over.
Tjah; dat is het vervelende van een abstract stuk code natuurlijk. Ik kan het wel uitleggen en weet ook vrij zeker dat ik geen lelijke oplossing aan het maken ben die met vage hacks zijn doel probeert te bereiken ;) Ik zou echter verwachten dat in een goed object model het destroyen van een object ook al zijn [lopende] code zou stoppen. Blijkbaar is dit echter niet het geval.

---
Prozium - The great nepenthe. Opiate of our masses. Glue of our great society. Salve and salvation, it has delivered us from pathos, from sorrow, the deepest chasms of melancholy and hate


Verwijderd

Ik kan het wel uitleggen en weet ook vrij zeker dat ik geen lelijke oplossing aan het maken ben die met vage hacks zijn doel probeert te bereiken
Weet je dat zeker? ;) M.i. is 't nogal ranzig om x->z naar of a of b te laten verwijzen, al naar gelang of x->r() is aangeroepen of niet.
Dat 't in PHP kan doet niets af aan het feit dat 't beroerde OO code is. :)

  • Spider.007
  • Registratie: December 2000
  • Niet online

Spider.007

* Tetragrammaton

Topicstarter
Verwijderd schreef op zondag 20 augustus 2006 @ 13:48:
[...]
Weet je dat zeker? ;) M.i. is 't nogal ranzig om x->z naar of a of b te laten verwijzen, al naar gelang of x->r() is aangeroepen of niet.
Dat 't in PHP kan doet niets af aan het feit dat 't beroerde OO code is. :)
Ik kan het denk wel als volgt illustreren:

a is een specifieke specialisatie [bijvoorbeeld een blauw extends kleur] en b is een specifieke specialisatie [bijvoorbeeld een rood extends kleur]. x heeft een kleur nodig en instantieert de kleur die op dat moment benodigd is. In sommige uitzonderlijke gevallen moet de kleur worden aangepast; en wordt x->z door blauw opnieuw ingesteld naar rood. Een kleur moet dus zelf kunnen besluiten dat hij niet de juiste kleur is voor de huidige situatie; en moet dus de controller kunnen laten weten dat deze een andere kleur moet gebruiken. Momenteel is het echter zo dat PHP de code binnen blauw laat doorlopen ondanks dat deze reeds heeft aangegeven niet de juiste kleur te zijn. In de huidige situatie [zoals ook door het voorbeeld geillustreerd] wordt na de kleur rood alsnog de kleur blauw uitgevoerd; ondanks dat blauw al in een vroeg stadium heeft laten weten niet de juist kleur te zijn. Blauw is hiermee dus verdwenen (immers vervangen door rood); echter voert PHP toch de code van dit niet meer bestaande object uit. Het is zelfs zo erg dat een get_class($this); binnen blauw gewoon 'rood' returned. De enige manier om dus na de $x->r() te controleren of er wellicht gereturned moet worden is door get_class($this); te vergelijken met de string 'blauw'; wat niet netjes is. Liever had ik get_class($this); vergeleken met $x->correcte_kleur welke door rood netjes is ingesteld op 'rood'

---
Prozium - The great nepenthe. Opiate of our masses. Glue of our great society. Salve and salvation, it has delivered us from pathos, from sorrow, the deepest chasms of melancholy and hate


  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 00:07

Creepy

Tactical Espionage Splatterer

Met deze uitleg zou ik i.p.v. een subclass alleen de superclass gebruiken (Kleur) welke de huidige kleur teruggeeft zodat je geen nieuwe hoeft te instantieren. Een andere kleur? Kleur->SetColor("rood") en gaan :)

Maar ik neem aan dat de echte situatie nog wat complexter is dan hier beschreven.....

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • Michali
  • Registratie: Juli 2002
  • Laatst online: 09-12-2025
Dit lijkt me niet echt de juiste taak voor Kleur. Een kleur is een kleur, en behoort naar mijn logica niet te controleren of hij zelf de juiste kleur in een bepaalde situatie is. Die taak geef je aan een andere class, de class die de kleur gaat toepassen, of eventueel een extra helper class.

Noushka's Magnificent Dream | Unity


  • Spider.007
  • Registratie: December 2000
  • Niet online

Spider.007

* Tetragrammaton

Topicstarter
Creepy schreef op zondag 20 augustus 2006 @ 14:44:
Met deze uitleg zou ik i.p.v. een subclass alleen de superclass gebruiken (Kleur) welke de huidige kleur teruggeeft zodat je geen nieuwe hoeft te instantieren. Een andere kleur? Kleur->SetColor("rood") en gaan :)

Maar ik neem aan dat de echte situatie nog wat complexter is dan hier beschreven.....
Als alleen het bovenstaande verhaal de huidige situatie zou beschrijven zou ik je gelijk geven; de reden dat jouw voorstel echter niet geimplementeerd kan worden is dat enerzijds de controller in 99% van de gevallen zelf de kleur bepaald (en die bepaling dus niet aan het kleur-object kan overlaten) en anderzijds dat de beslissing om een andere kleur te instantieren altijd volgt uit een stuk logica wat specifiek is per kleur; en niet generiek kan worden bepaald. Daaruit volgt dus de behoefte het actieve kleurobject te vervangen door een andere kleur; en daarmee is het vervelend dat PHP beide objecten op eigen houtje door elkaar mixed :)
Michali schreef op zondag 20 augustus 2006 @ 15:17:
Dit lijkt me niet echt de juiste taak voor Kleur. Een kleur is een kleur, en behoort naar mijn logica niet te controleren of hij zelf de juiste kleur in een bepaalde situatie is. Die taak geef je aan een andere class, de class die de kleur gaat toepassen, of eventueel een extra helper class.
Het daadwerkelijke probleem ligt dan ook ietwat anders; met als gevolg dat een kleur als enige de logica kan bevatten om te besluiten dat zijn object onjuist wordt gebruikt; en dat een ander kleur object benodigd is voor het uitvoeren voor de gewenste actie. Hoe onlogisch is het om dan de controller een ander kleurobject te laten instantieeren; en hoe logische is het vervolgens dat PHP toch 1 functie uit het oude object laat bestaan?

[ Voor 28% gewijzigd door Spider.007 op 20-08-2006 15:47 ]

---
Prozium - The great nepenthe. Opiate of our masses. Glue of our great society. Salve and salvation, it has delivered us from pathos, from sorrow, the deepest chasms of melancholy and hate


Verwijderd

Hoe je 't ook wendt of keert, 't blijft ranzig.
Wanneer je x aanmaakt die vervolgens a aanmaakt, en a vertelt dan dat 'ie vervangen moet worden door b, dan heb je een probleem in je ontwerp.
Geef me 1 goede reden waarom dit op zo'n kromme manier moet, en geef dan ook nog 's aan hoe zulke source goed onderhoudbaar is door anderen?

  • Erkens
  • Registratie: December 2001
  • Niet online

Erkens

Fotograaf

Spider.007 schreef op zondag 20 augustus 2006 @ 15:41:
Het daadwerkelijke probleem ligt dan ook ietwat anders; met als gevolg dat een kleur als enige de logica kan bevatten om te besluiten dat zijn object onjuist wordt gebruikt; en dat een ander kleur object benodigd is voor het uitvoeren voor de gewenste actie. Hoe onlogisch is het om dan de controller een ander kleurobject te laten instantieeren; en hoe logische is het vervolgens dat PHP toch 1 functie uit het oude object laat bestaan?
php houdt een pointer bij naar die bepaalde functie, een unset oid zal dan ook alleen binnen de huidige scope uitgevoerd worden (in sommige gevallen, helaas), en aangezien $this "reserved" is, kan je deze niet unsetten.
Maar als dit je probleem is dan denk ik dat er weinig anders opzit om je objecten zelf bij te laten houden dat ze niet gebruikt kunnen worden. Ik weet overigens niet hoe complex de echte situatie is, maar is het niet mogelijk om mbv een static functie te bepalen of het betreffende object gebruikt kan worden alvorens deze te maken?
Pagina: 1