PHP5: Referenties naar niet bestaande objecten

March 10th, 2007 by Davy

Een tijdje geleden zat ik vrij OO bezig en stuitte ik op iets wat ik eigenlijk had moeten voorzien. Eén hoofdclass hield een template object bij en een drietal andere classes hadden een referentie naar dit object. Onder zekere voorwaarden werd het eigenlijke object opnieuw aangemaakt. Hierdoor gingen alle referenties in die drie andere classes op zichzelf bestaan en was de “verwijzing” niet langer..

code1.png

output.png

Het relaas van dit alles is vrij simpel. Als je éénzelfde object van verschillende locaties aanspreekt, kijk dan goed uit als je dit object om de één of andere reden opnieuw zou moeten aanmaken, want de verwijzingen zijn “dood”.

10 Responses to “PHP5: Referenties naar niet bestaande objecten”

  1. Frank says:

    Hmm, ge gaat uw OO boek toch nog eens moeten lezen :) Wat je doet met “unset()” is een variabele unsetten. (Soms zijn functienamen goed gekozen he?) Wat je niet doet, is dat object volledig deleten. Je verwijdert enkel de link tussen wat jij “$whip” noemt, en een bepaalde instantie van de klasse Whiplash. Jammer dat je in PHP geen ‘free()’ functie hebt die wel een object compleet kan deleten. De garbage-collector (de mannen van den ivago) komen pas om je object als er geen enkele referentie meer naar bestaat.

    Wat je ziet, is dus perfect documented en expected behaviour!

  2. Jan says:

    En je geeft ook niet echt per referentie mee. PHP gaat zich misschien wel zo gedragen voor sommige objecten maar als je expliciet iets byref wil meegeven moet je werken met &$object. Zie http://php.mirror.camelnetwork.com/manual/en/language.references.php

  3. Slicer says:

    @Jan: je bent fout, vanaf php5 geeft php standaard objectjen by reference mee

    En Frank heeft natuurlijk volledig gelijk, het gedrag is perfect normaal.

  4. Jan says:

    @Slicer: correct, maar daar zeg je het meteen, objecten. Aangezien je niet altijd weet wat je gaat meegeven is het aan te raden je by-references er expliciet in te steken, want bij strings en int geeft hij ze nog steeds niet by-ref mee.

  5. Davy says:

    @Frank, als ik nu 3 classes had dan zouden dit 3 aparte op zich zelf bestaande objecten worden, door het unsetten van de $whip variabele. Daar zijn we het over eens right?

  6. Frank says:

    Davy, euh, nee? Aangezien het objecten zijn, worden die byref ipv byval doorgegeven (objecten byval doorgeven is trouwens vies en memory/cpu duur). Het is hetzelfde object.

    Maw: stel dat je hebt (pseudocode, heb nog geen 2 koffies op, dus er komt nog geen echte code uit):

    $Ei = new Whiplash(“Paasei”);
    $BelgischMandje = new Foo($Ei);
    $LuxemburgsMandje = new Foo($Ei);
    $ZwitsersMandje = new Foo($Ei);

    unset($Ei);

    Je 3 mandjes bevatten nog altijd dezelfde instantie van het object Whiplash. Stel dat je een functie in uw klasse Foo hebt die iets aanpast aan uw deelobject, dan ga je zien dat het bij de andere ook aangepast is. Als dat niet zo zou zijn, mag PHP zich nooit meer een OO taal noemen :)

    Frank
    (ps: $FiscusControleur kan aan je drie mandjes! Ha!)

  7. Davy says:

    Deze middag ff een brok code in mekaar plakken zoals het was, dan zie je waar mijn wrevel zich bevindt ;)

  8. Bernard says:

    Het gedraagt zich toch zoals het hoort. De unset functie doet misschien niet wat je verwacht dat ze doet, maar php heeft (zoals Frank) al aanhaalt geen mogelijkheid om een object expliciet en geforceerd te destroyen.

    Een object heeft een lifetime. Deze is helemaal niet gekoppeld aan een variabele die toevallig de referentie heeft. Er bestaat geen manier om dat via een voorbeeldje weer te geven, maar in jullie voorbeeld is $whip slechts een eenvoudige verwijzing naar dat object. Er kunnen 1, 10, 20 of 100 verwijzingen zijn. Zolang er verwijzingen zijn, bestaat het object (en kan je eraan). Verwijzingen weg == object is “lost in space”, en normaal gaat de garbage collector dan langskomen om dat op te ruimen. Als ik eens wat meer tijd heb, ga ik dat eens proberen aan te tonen. Ik ben zelfs niet zeker dat de garbage collector onmiddellijk langskomt.

    Misschien nog meer schokkend: de destructor van php gaat zelfs het object niet verwijderen, die voert gewoon de functie uit, maar het object blijft bestaan. Wanneer je dus een referentie hebt naar een ge-destruct object, dan kan je dit verder blijven gebruik. Zeer vies. Maar we wisten al dat php het OO-luik ietwat smerig opgelost had. Bij php5 is het al een stuk beter, maar nog altijd heeft het scherpe kantjes. (Reden te meer om naar ruby over te schakelen, wat een echte OO-taal is ;) ).

  9. Felix says:

    Hallo

    way to late om een reactie te geven natuurlijk maar ik kwam op deze pagina via een grote zoekmachine. Objects worden in PHP5 niet by ref meegegeven. Ze doen alsof ze by reference worden meegegeven maar intern worden ze anders verwerkt. For an example: http://blog.libssh2.org/index.php?/archives/51-Youre-being-lied-to..html

  10. Îòåëè Âüåòíàìà says:

    Ëó÷øèå ïëÿæè Þæíî-Êèòàéñêîãî ìîðÿ…

    Âüåòíàì – ñòðàíà ñ äðåâíåéøåé èñòîðèåé è êóëüòóðîé…

Leave a Reply