Ankündigung

Einklappen
Keine Ankündigung bisher.

Public method call nur über Master-Object zulassen

Einklappen

Neue Werbung 2019

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

  • Public method call nur über Master-Object zulassen

    Sorry für das denglisch
    Einleitend erstmal ein bisschen abstrakter Code zur Veranschaulichung.
    PHP-Code:
    class ItemCollection
    {

      protected 
    $items = array();

      public function 
    __construct()
      {
        foreach(
    range(042) as $index)
        {
          
    $this->items[$index] = new Item($this);
        }
      }

      public function 
    setItemProperty($itemIndex$property)
      {
        
    $this->items[$itemIndex]->setProperty($property);
      }

    }

    class 
    Item
    {

      protected 
    $itemCollection null;

      protected 
    $property null;

      public function 
    __construct(ItemCollection $itemCollection)
      {
        
    $this->index $index;
        
    $this->itemCollection $itemCollection;
      }

      
    // Dieser Aufruf soll nur über
      // $ItemCollection->setItemProperty($itemIndex, $property)
      // zugelassen werden
      
    public function setProperty($property)
      {
        
    $this->property $property;
      }


    Mir geht um die Methode setItemProperty($itemIndex, $property) in ItemCollection. Diese Methode ruft wiederum die entsprechende Methode des betreffenden Item-Objektes auf.
    Jetzt meine Frage: Kann ich es verhindern, dass die Methode direkt über das Item-Objekt aufgerufen wird, da ja setProperty($property) public access hat?

  • #2
    Nö. Weil public und Co eben nur Sichtbarkeiten, keine Zugriffskontrolle darstellen.

    Kommentar


    • #3
      Hier hat das mal jemand mit __call und debug_backtrace implementiert. Ist interessant anzuschauen aber meiner Meinung nach zu frickelig als dass es wirklich praktikabel wäre.

      Ich würde setItemProperty einfach nicht anderswo aufrufen und das in der Dokumentation festhalten. Eine Namenskonvention wie vorangestellter Unterstrich kann auch nicht schaden um die Methode direkt von "echt public" Methoden zu unterscheiden.

      Kommentar


      • #4
        Zitat von fab Beitrag anzeigen
        Hier hat das mal jemand mit __call und debug_backtrace implementiert. Ist interessant anzuschauen aber meiner Meinung nach zu frickelig als dass es wirklich praktikabel wäre.
        Die Idee, den Methoden-Aufruf zu tracen kam mir auch in den Sinn, aber wegen des besagten Frickelfaktors auch gleich wieder verworfen Ich dachte, es gäbe da vielleicht eine elegante Restriktion.

        Danke auch für deine anderen Ausführungen.

        Kommentar


        • #5
          Zitat von fab Beitrag anzeigen
          Eine Namenskonvention wie vorangestellter Unterstrich kann auch nicht schaden um die Methode direkt von "echt public" Methoden zu unterscheiden.
          Das gefällt mir ganz gut!
          Ist die Idee von dir oder wird es üblicherweise so gehandhabt, um dieses "Problem" zu umschiffen?

          Kommentar


          • #6
            gibts nur in c sowas (friends). evtl. geht das mit traits zu machen, aber das würde auch in hässlichem code resultieren.

            Kommentar


            • #7
              Aha, "friends" nennt sich dieses Konstrukt.

              Zu der Unterstrich-Konvention ist mir gerade aufgefallen, dass das im Konstruktor ähnlich gehandhabt wird.
              PHP-Code:
              class Test
              {
                public function 
              __construct()
                {
                  echo 
              __METHOD__.'<br />';
                }
              }

              $test = new Test();
              $test->__construct(); 
              Code:
              Test::__construct
              Test::__construct
              Den Konstruktor sollte man ja im nachhinein, also an einer bestehenden Instanz auch nicht aufrufen sollen/dürfen - möglich ist es aber.

              Kommentar


              • #8
                Zitat von hts Beitrag anzeigen
                Das gefällt mir ganz gut!
                Ist die Idee von dir oder wird es üblicherweise so gehandhabt, um dieses "Problem" zu umschiffen?
                Kann sein dass ich das schonmal woanders gesehen habe, es ist jedenfalls naheliegend, da in den PEAR und Zend Coding Standards auch private und protected mit Unterstrich gekennzeichnet wird.

                Der doppelte Unterstrich hat aber eine andere Bedeutung: Magic Methods
                PHP reserviert alle Funktionsnamen, die mit __ beginnen, als magisch. Es wird empfohlen, keine Funktionsnamen mit __ in PHP zu benutzen, es sei denn, man möchte dokumentierte magische Funktionalität verwenden.

                Kommentar


                • #9
                  Meiner Meinung nach sollte die Manipulation der Elemente einer Collection über deren Methoden erfolgen, sprich:

                  PHP-Code:
                  $ItemCollection->getItem('foo')->setProperty($property); 

                  Kommentar


                  • #10
                    Zitat von Trainmaster Beitrag anzeigen
                    Meiner Meinung nach sollte die Manipulation der Elemente einer Collection über deren Methoden erfolgen
                    Klaro, nur fände ich es nur schön, wenn PHP die Daumenschraube ansetzen würde, wenn man sich nicht daran hält. Das war ja die Intention meiner Frage.

                    Als Vergleich mal vielleicht: MyISAM vs. InnoDB bezüglich FOREIGN KEY.
                    Bei MyISAM kann man auch in der Programmierlogik darauf achten, das die Schlüsselbezieheungen passen, bei InnoDB weiß man, dass sie passen - verstehst du?

                    Kommentar


                    • #11
                      Zitat von hts Beitrag anzeigen
                      Sorry für das denglisch
                      Einleitend erstmal ein bisschen abstrakter Code zur Veranschaulichung.

                      Mir geht um die Methode setItemProperty($itemIndex, $property) in ItemCollection. Diese Methode ruft wiederum die entsprechende Methode des betreffenden Item-Objektes auf.
                      Jetzt meine Frage: Kann ich es verhindern, dass die Methode direkt über das Item-Objekt aufgerufen wird, da ja setProperty($property) public access hat?
                      Ja, technisch schon:
                      PHP-Code:
                      class Item {

                          private
                              
                      $itemCollection$property;
                              
                          public function 
                      __constructItemCollection $itemCollection ) {
                              
                      $this->itemCollection $itemCollection;
                          }
                          
                          protected function 
                      setProperty$property ) {
                              
                      $this->property $property;
                          }

                      }

                      class 
                      ItemCollection extends Item {
                          
                          private
                              
                      $items = array();
                              
                          public function 
                      __construct() {
                              foreach ( 
                      range(0,42) as $index )
                                  
                      $this->items[$index] = new Item($this);
                          }
                          
                          public function 
                      setItemProperty($itemIndex$property) {
                              
                      $this->items[$itemIndex]->setProperty($property);
                          }
                          

                      Aber: Allgemein möchte man das "verbiegen" von Vererbung hier als Fail-Design ansehen, rein von der technischen Machbarkeit her ist dieser Weg aber der einzige.

                      Die andere geschichte wäre in diesem Fall ein "Wartungsobjekt" zu implementieren, unzwar genau eins, und den gesamten Datenbestand im Collection-Objekt belassen.

                      Du gaukelst also der "Aussenwelt" vor das dort x Objekte im Array sind, was die verletzbarkeit von zugriffen angeht, ist das aber mehr oder weniger ein paranoides Umschiffen und Grundsätzlich kein besseres Design als das obige.

                      PHP-Code:
                      class Item {

                          private 
                      $itemCollection$property;

                          public function 
                      __constructItemCollective $icol ) {
                              
                      $this->itemCollection $icol;
                          }
                          
                          public function 
                      setProperty$propertyClosure $lambda null ) {
                              if ( !
                      is_null($lambda) ) {
                                  
                      $lambda($property);
                                  
                      $this->property $property;
                                  unset(
                      $lambda);
                              }
                          }
                          
                          public function 
                      getProperty() {
                              return 
                      $this->property;
                          }

                      }

                      class 
                      ItemCollective {

                          private
                              
                      $items = array();
                              
                          public function 
                      __construct() {
                              foreach ( 
                      range(0,42) as $index ) {
                                  
                      $this->items[$index] = array();
                              }
                          }
                          
                          public function 
                      setItemProperty($itemIndex$property) {
                              
                      $obj = new Item($this);
                              
                      $obj->setProperty(
                                  
                      $property,
                                  
                      $this->exposePropertyAccess$this->items[$itemIndex] )
                              );
                          }
                          
                          public function 
                      getItem($itemIndex) {
                              
                      $obj = new Item($this);
                              
                      $obj->setProperty(
                                  
                      null,
                                  
                      $this->inspectPropertyAccess$this->items[$itemIndex] )
                              );
                              return 
                      $obj;
                          }
                          
                          protected function 
                      exposePropertyAccess( &$data ) {
                              return function ( 
                      $newProperty ) use ( &$data ) {
                                  
                      $data['property'] = $newProperty;
                              };
                          }
                          
                          protected function 
                      inspectPropertyAccess( &$data ) {
                              return function ( &
                      $current ) use ( &$data ) {
                                  
                      $current $data['property'];
                              };
                          }


                      Was die hier auch genannte __construct()-Aufrufbarkeit angeht, auch die Umschifft man indem man die zu initialisierenden Variablen nutzt und deren nicht-initialisiert-Zustand als Bedingung prüft.

                      Was genau willst du denn erreichen ? Prinzipiell sollten doch einzelne Elemente einer Collection wohl erreichbar sein und sie sind via Collection-Objekt auch modifizierbar. Wo ist das Problem wenn dort das Objekt an sich halt auch "public" die möglichkeit bietet es zu modifizieren ? Der setItemProperty()-Aufruf ist doch nichts weiter als ein Methoden-Mapping in eine andere Klasse, ergo Jacke wie Hose.

                      Kommentar

                      Lädt...
                      X