Ankündigung

Einklappen
Keine Ankündigung bisher.

Destruktor / Instanz löschen

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Destruktor / Instanz löschen

    Hallo,

    ich habe mal eine Frage zu dem Destruktor in PHP.
    Dazu habe ich eine Klasse test geschrieben mit Konstruktor und Destruktor.

    Ist das soweit richtig und für eine "saubere" Programmierung auch nötig ?

    Am Ende des Skripts wird die geschaffene Instant "genullt" und per unset gelöscht. Ist das soweit auch richtig und nötig ?

    Danke!!

    PHP-Code:
    <?php
    class test
    {
        private 
    $a;
        private 
    $b;
        
        function 
    __construct()
        {
            
    $this->5;
            
    $this->10;
        }

        
        function 
    __destruct()
        {
            unset(
    $this->a);
            unset(
    $this->b);
        }
    }

    $test_class = new test();

    ...
    ...

    $test_class NULL;
    unset(
    $test_class);
    ?>
    Noch eine kleine Frage: Ab welcher PHP-Version werden Exceptions und __destruct unterstützt ? Erst ab PHP5 ?


  • #2
    Zitat von loobster
    Am Ende des Skripts wird die geschaffene Instant "genullt" und per unset gelöscht. Ist das soweit auch richtig und nötig ?
    Das beantworte ich mal mit einem entschiedenen: jein

    Im Handbuch steht dazu
    Zitat von http://uk2.php.net/manual/en/language.oop5.decon.php
    The destructor method will be called as soon as all references to a particular object are removed or when the object is explicitly destroyed or in any order in shutdown sequence.
    Mit
    PHP-Code:
    $test_class NULL
    löst Du bereits die Referenz auf - gibt es keine weiteren Referenzen, sollte PHP das Objekt hier schon auf die Abschussliste setzen.
    Das darauf folgende unset() hat dann also keinen Bezug mehr zu dem Objekt und damit auch keine Relevanz mehr, was den Destruktor angeht. Wenn Du die =NULL-Zeile streichst, räumt unset($test_class) die Referenz auf das Objekt auch ab.
    Wenn der Sichtbarkeitsbereich einer Variablen verlassen wird, zum Beispiel
    PHP-Code:
    function foo() {
      
    $x 1;
      
    // Ende der Funktion. $x ist nur lokal definiert -> Ende des Sichtbarkeitsbereichs von $x

    sollten Variablen auch abgeräumt werden. samt Referenzzähler und ggf. Aufruf von Destruktoren. "Sollten" weil ich schon öfter von Problemen gelesen habe. Wie das aktuell aussieht, weiß ich ehrlich gesagt nicht.
    Das Ende der Skriptabarbeitung ist nochmal ein Sonderfall.
    Zitat von http://uk2.php.net/manual/en/language.oop5.decon.php
    Note: Destructors called during the script shutdown have HTTP headers already sent. The working directory in the script shutdown phase can be different with some SAPIs (e.g. Apache).
    Note: Attempting to throw an exception from a destructor (called in the time of script termination) causes a fatal error.
    Wenn Du also Objekte im globalen Namensraum "liegen lässt" und PHP sie deshalb automatisch am Ende abräumt, gelten ein bisschen andere Regeln.


    Also kurz gesagt: die Zeile
    $test_class = NULL;
    kann raus.
    Und auch erstmal nicht zu viel über Destruktoren nachdenken. In Deinem Skript sehe ich zum Beispiel gar keinen Grund dafür. PHP übernimmt in diesem Fall die Speicherverwaltung von sich aus.

    Kommentar


    • #3
      @David:
      Danke für deine schnelle und ausführliche Antwort, dann werde ich das "=NULL" streichen

      Aber der Destruktor innerhalb der Klasse hat seine Daseins-Berechtigung ?

      PHP-Code:
      function __destruct()
          {
              unset(
      $this->a);
              unset(
      $this->b);
          } 

      Kommentar


      • #4
        In Deinem Beispiel ist er überflüssig. Wie gesagt kümmert sich PHP an dieser Stelle selbst darum.

        Kommentar


        • #5
          Der Destruktur dient nicht zum Löschen des Objekts, sondern zum Ausführen von Aktionen direkt vor dem Löschen desselben.
          --

          „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
          Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


          --

          Kommentar


          • #6
            Zitat von nikosch Beitrag anzeigen
            Der Destruktur dient nicht zum Löschen des Objekts, sondern zum Ausführen von Aktionen direkt vor dem Löschen desselben.
            Ist es denn noch nötig die beiden Variablen zu löschen oder werden die dann automatisch mit der Zeile
            PHP-Code:
            unset($test_class); 
            gelöscht ?

            Kommentar


            • #7
              Letzteres. Es sei denn, Du rufst den Destruktor explizit auf. Was dann mit dem Objekt passiert, bin ich mir nicht ganz sicher.
              --

              „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
              Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


              --

              Kommentar


              • #8
                Hast Du vorher eine Sprache ohne (automatische) Speicherverwaltung erlernt? C, C++ ?

                Kommentar


                • #9
                  Zitat von David Beitrag anzeigen
                  Hast Du vorher eine Sprache ohne (automatische) Speicherverwaltung erlernt? C, C++ ?
                  Jo, C++

                  Kommentar


                  • #10
                    Ich hab ma irgendwo gelesen, dass = NULL besser als unset sein soll, weil es den Speicher freigibt. Sorry wegen Threadmissbrauch, aber weiß jemand was dazu?

                    Mir fällt noch ein, dass man mit den ganzen Referenzen verdammt aufpassen und ggf. Flags und klaren Destruktoraufruf verwenden muss (Wenn man zum Beispiel selbst die Zerstörungsreihenfolge festlegen will...).

                    Kommentar


                    • #11
                      Dass zirkuläre Referenzen in PHP ein Problem sind, kannst man am Beispiel
                      PHP-Code:
                      <?php
                      class Foo {
                        protected 
                      $id;
                        public 
                      $ref null;
                        public function 
                      __construct($id) {
                          
                      $this->id $id;
                        }
                        
                        public function 
                      __destruct() {
                          echo 
                      '- '$this->id " wird abgeräumt\n";
                        }
                      }

                      function 
                      bar($loop) {
                        
                      $a = new Foo('A'.$loop);
                        
                      $b = new Foo('B'.$loop);
                        
                      $c = new Foo('C'.$loop);
                        
                        
                      $a->ref $b;
                        
                      $b->ref $c;
                        if ( 
                      $loop ) {
                          
                      $c->ref $a;
                        }
                      }
                      echo 
                      PHP_VERSION' 'PHP_OS' 'PHP_SAPI"\n";
                      echo 
                      "Aufruf von bar(0)\n";
                      bar(0);
                      echo 
                      "Aufruf von bar(1)\n";
                      bar(1);
                      echo 
                      "Skriptende\n";
                      5.2.6 WINNT cli
                      Aufruf von bar(0)
                      - A0 wird abgeräumt
                      - B0 wird abgeräumt
                      - C0 wird abgeräumt
                      Aufruf von bar(1)
                      Skriptende
                      - C1 wird abgeräumt
                      - B1 wird abgeräumt
                      - A1 wird abgeräumt
                      sehen. Die Instanzen A0, B0, C0 werden beim Verlassen ihres Sichtbarkeitsbereiches (beim Verlassen der Funktion) abgeräumt. A1,B1,C1 - also die mit der Kreisreferenz - erst am Ende des Skripts.

                      Zitat von Phlegma
                      Ich hab ma irgendwo gelesen, dass = NULL besser als unset sein soll, weil es den Speicher freigibt.
                      Das wäre dann ein direkter Fehler in unset(). Kann aber auch durchaus möglich sein, dass es so eine Version von PHP gibt

                      Kommentar


                      • #12
                        Nicht sehr übersichtlich dieses Beispiel.
                        Die Instanzen A0, B0, C0 werden beim Verlassen ihres Sichtbarkeitsbereiches (beim Verlassen der Funktion) abgeräumt. A1,B1,C1 - also die mit der Kreisreferenz - erst am Ende des Skripts.
                        Aber wieso ist das problematisch? Ist doch nötig, dass das Objekt erhalten bleibt.
                        --

                        „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
                        Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


                        --

                        Kommentar


                        • #13
                          In zwei Skripten ist es vielleicht übersichtlicher, ja.
                          Zitat von nikosch
                          Ist doch nötig, dass das Objekt erhalten bleibt.
                          Keines der Objekte ist mehr zugänglich. Wie ein kleines Schwarzes Loch.


                          Einfacheres Beispiel
                          PHP-Code:
                          <?php
                          class Foo {
                            public function 
                          __destruct() {
                              echo 
                          "*";
                            }
                          }

                          $a = new Foo;
                          $b = new Foo;
                          $a->ref $b;
                          $b->ref $a;

                          unset(
                          $a);
                          unset(
                          $b);
                          echo 
                          'Skriptende';
                          Skriptende**

                          Kommentar


                          • #14
                            Naja, gut. Da hast Du natürlich recht. Ohne Funktionsrückgabe reichlich sinnfrei.
                            --

                            „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
                            Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


                            --

                            Kommentar

                            Lädt...
                            X