Ankündigung

Einklappen
Keine Ankündigung bisher.

Typ bei jeder Methode prüfen

Einklappen

Neue Werbung 2019

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

  • Typ bei jeder Methode prüfen

    Hallo, lerne gerade OOP in PHP und frage mich, ob ich bei jeder Methode, die einen Übergabeparameter erwartet, prüfen soll, ob dieser vom erwarteten Typ ist. Habt ihr nen Rat, bzw. wie macht ihr das?
    P.S. Ich komme aus der typsicheren Java-Welt.


  • #2
    Dort, wo es geht (Klassen, Interfaces, Arrays, …), würde ich immer Typehints nutzen. Bei primitiven Datentypen (int, float, bool, string) prüfe ich in öffentlichen API-Methoden in der Regel auch, ob der übergebene Datentyp passt (is_int, is_float usw.), und werfe sonst eine Exception.

    Kommentar


    • #3
      Ok, und wenn du sowas hast?
      PHP-Code:
      <?php
      class First{

          public function 
      foo($a){
              
      $this->$a;
          }

      }

      class 
      Second{

          public function 
      __construct(){
              
      $this->first = new First();
          }

          public function 
      bar($b$c){
              
      $this->first->foo($b);
              
      //....
          
      }

      }
      Natürlich nur als sehr abstraktes Beispiel. Hier ist stellt sich für mich die Frage, wo du den Typ, des Parameters der Methode foo prüfst. Diese wird von bar aufgerufen. Nur in foo in der Klasse First, oder sowohl in foo als auch bar? Ich habe oft Konstrukte des SRP wegen, weshalb ich oft lange public Methoden in private Methoden aufspalte und ein ähnliches Problem habe.

      Kommentar


      • #4
        Eigentlich überprüft man jeden Parameter in der jeweiligen Methode, soweit man kein Typehint benutzen kann (fürprimitive Datentypen), also in deinem Beispiel $b in der Methode bar() und auch $a in der Methode foo().
        There are 10 kind of people: those who understand binary and those who don't.

        Kommentar


        • #5
          Aber selbst wenn ich $b in bar() nicht prüfe und was falsches eingebe bekomme ich trotzdem ne Exception, weil ich $a in foo() überprüfe. Deshalb frage ich ja, weil das theoretisch ein wenig Overhead ist.

          Kommentar


          • #6
            Zitat von hartCoder Beitrag anzeigen
            Aber selbst wenn ich $b in bar() nicht prüfe und was falsches eingebe bekomme ich trotzdem ne Exception, weil ich $a in foo() überprüfe. Deshalb frage ich ja, weil das theoretisch ein wenig Overhead ist.
            Aber nur, wenn Du davon ausgehst, dass Du $b nur für den Methodenaufruf foo() benutzt. Vielliecht erweiterst Du später Deine Methode bar() und verwendest den Parameter $b noch anderweitig. Also gewöhnt man sich am besten an immer alle Parameter einer Methode zu prüfen.
            There are 10 kind of people: those who understand binary and those who don't.

            Kommentar


            • #7
              Zitat von Padal Beitrag anzeigen
              Hallo, lerne gerade OOP in PHP und frage mich, ob ich bei jeder Methode, die einen Übergabeparameter erwartet, prüfen soll, ob dieser vom erwarteten Typ ist.
              Ja, wann immer es möglich ist.

              Habt ihr nen Rat, bzw. wie macht ihr das?
              Wie schon gesagt: Wann immer es möglich ist.
              Neben den "nicht-hintbaren" Typen gibts noch das Problem, dass PHP keine überladbaren Funktionen hat. Die in Java typischen Funktionsdeklarationen mit gleichem Funktionsnamen aber unterschiedlichen Typen für Parameter kann man in PHP nur simulieren, indem man zur Laufzeit den Typ abfragt. Da fallen Type-Hints natürlich aus.

              P.S. Ich komme aus der typsicheren Java-Welt.
              Dann wirst du bald merken, dass Typehints in PHP keine statische Typprüfung sind, sondern simple Checks während der Laufzeit. Du bekommst also die Typfehlermeldung nicht, wenn das Programm übersetzt wird, sondern erst, wenn die Funktion|Methode aufgerufen wird.

              Außerdem gibts in PHP (fast wie in Java) unterschiedliche Klassen von Typen:
              • Die eingebauten, wie Integer, Double, String, Resource, ..., auf die du nicht prüfen kannst (das Google-Stichwort dazu lautet "scalar typehints").
              • Die "besseren" Typen Array und Object, mit denen Typehinting möglich ist.
              • Null ist kein Typ, wird aber unter bestimmten Umständen als Argument akzeptiert.
              • Es gibt nur von benutzerdefinierten Objekten eine brauchbare Typhierarchie, die eingebauten Typen existieren oft fröhlich nebeneinander her oder der Basistyp ist wenig von Nutzen. Beispiele wären:
                • object, StdClass
                • array, Traversable (und Iterator)
                • DateTimeImmutable und DateTime implementieren mehr (nützliche) Methoden als DateTimeInterface zusichert.

              • Es gibt keine Möglichkeit, die Typen von Array-Elementen zu prüfen (außer man durchläuft das ganze Array zur Laufzeit).
              • Und um die Sache noch etwas verwirrender zu machen, gibt es auch noch Pseudo-Typen wie Callable, die irgendwelchen historisch gewachsenen Unsinn kompensieren sollen.


              Funktionsrückgabewerte kann man derzeit in gewöhnlichem PHP auch noch nicht deklarieren (in HHVM schon). Das soll aber in der nächsten Version (PHP7) möglich werden.

              Viel Spaß werden dir auch die impliziten Typkonvertierungen machen.
              Wenn man die Wurst schräg anschneidet, hält sie länger, weil die Scheiben größer sind.

              Kommentar


              • #8
                @Talwin, fireweasl: Vielen Dank euch beiden!

                Kommentar


                • #9
                  (*doppelpost-gelöscht*)
                  Wenn man die Wurst schräg anschneidet, hält sie länger, weil die Scheiben größer sind.

                  Kommentar


                  • #10
                    mermshaus #2 hat es kurz umrissen, wie es viele machen. Ich dagegen nutze gerne die Ungebundenheit von Parametern an einen bestimmten Typ schamlos aus, soweit es Sinn macht. Oder anders gesagt, prüfen ja, fest binden nein.
                    Um das zu verdeutlichen mal ein Beispiel (die Klasse ist nicht von mir!):
                    PHP-Code:
                    $dt = new carbon('1975-03-25', new DateTimeZone('Europe/Berlin'));
                    $dt2 = new carbon('1975-03-25''Europe/Berlin');
                    //$dt = new carbon('1975-03-25', 356);  //würde Fatal-Error auslösen 
                    Der Konstruktor von carbon prüft auf einen einen String. Wenn der vorliegt wird intern ein DateTimeZone-Objekt erstellt. Wird das passende Objekt geliefert, wird es genommen. Eine Exception wird geworfen, wenn Unsinn angeliefert wird.

                    In der Funktionsreferenz des PHP-Kerns finden sich zahlreiche Funktionen, welche mixed Parameter akzeptieren. Das sehe ich als großen Vorteil von PHP. Warum soll dies nicht auch bei der OOP genutzt werden?
                    PHP-Klassen auf github

                    Kommentar


                    • #11
                      Das wäre dann quasi ein Umweg um doch so etwas ähnliches wie überladene Methoden zu erzeugen, das mache ich auch ab und zu so.
                      There are 10 kind of people: those who understand binary and those who don't.

                      Kommentar


                      • #12
                        Zitat von jspit Beitrag anzeigen
                        mermshaus #2 hat es kurz umrissen, wie es viele machen. Ich dagegen nutze gerne die Ungebundenheit von Parametern an einen bestimmten Typ schamlos aus, soweit es Sinn macht. Oder anders gesagt, prüfen ja, fest binden nein.
                        Um das zu verdeutlichen mal ein Beispiel (die Klasse ist nicht von mir!):
                        PHP-Code:
                        $dt = new carbon('1975-03-25', new DateTimeZone('Europe/Berlin'));
                        $dt2 = new carbon('1975-03-25''Europe/Berlin');
                        //$dt = new carbon('1975-03-25', 356);  //würde Fatal-Error auslösen 
                        Der Konstruktor von carbon prüft auf einen einen String. Wenn der vorliegt wird intern ein DateTimeZone-Objekt erstellt. Wird das passende Objekt geliefert, wird es genommen. Eine Exception wird geworfen, wenn Unsinn angeliefert wird.
                        Hehe, fast das gleiche Beispiel (DateTimeZone vs. Timezone-String) schwebte mir auch vor.

                        PHP-Code:
                        class DateTimePHPNow {

                            function 
                        __construct(whatever $datetime$tzone) {
                                
                        $this->datetime = new DateTime($datetime);

                                
                        $this->tzone $tzone instanceof DateTimeZone
                                    
                        $tzone
                                    
                        : new DateTimeZone($tzone);
                            }

                        Naja, gut, es soll da noch ein paar Möglichkeiten mehr geben, eine Zeitzone zu definieren ...

                        PHP-Code:
                        class DateTimePHPNowErrrrm {

                            function 
                        __construct(whatever $datetime$tzone) {
                                
                        $this->datetime = new DateTime($datetime);

                                if (
                        $tzone instanceof DateTimeZone) {
                                    
                        $this->tzone $tzone;
                                }
                                elseif (
                        $tzone instanceof IntlTimeZone) {
                                    
                        $this->tzone $tzone->toDateTimeZone();
                                }
                                elseif (
                        is_int($tzone)) {
                                    
                        $this->tzone = new DateTimeZone(
                                        
                        sprintf(
                                            
                        '%+02d:%02d',
                                            
                        $h = (int) $offset_in_secs 3600,
                                            (int) 
                        $offset_in_secs 60 $h 60
                                        
                        )
                                    );
                                }
                                else {
                                    
                        $this->tzone = new DateTimeZone($tzone);
                                }

                                if (!(
                        $this->tzone instanceof DateTimeZone)) {
                                    throw new 
                        TypeError();
                                }

                            }

                        PHP-Code:
                        class DateTimePHPAndThenMayBeProbably {

                            function 
                        __construct(whatever $datetimeDateTimeZone $tzone) {
                                
                        $this->datetime = new DateTime($datetime);
                                
                        $this->tzone $tzone;
                            }

                            function 
                        __construct(whatever $datetimestring $tzone) {
                                
                        $this->__construct($datetime, new DateTimeZone($tzone));
                            }

                            function 
                        __construct(whatever $datetimeIntlTimeZone $tzone) {
                                
                        $this->construct($datetime$tzone->toDateTimeZone());
                            }

                            function 
                        __construct(whatever $datetimeinteger $offset_in_secs) {
                                
                        $this->__construct(
                                    
                        $datetime,
                                    new 
                        DateTimeZone(
                                        
                        sprintf(
                                            
                        '%+02d:%02d',
                                            
                        $h = (int) $offset_in_secs 3600,
                                            (int) 
                        $offset_in_secs 60 $h 60
                                        
                        )
                                );
                            }

                            function 
                        __construct(whatever $datetimedouble $longitude) {
                                
                        $this->construct($datetime, (int) $longitude 240);
                            }

                            function 
                        __construct(whatever $datetime, array $lat_long) {
                                
                        $this->construct($datetimeTimeZoneDBWsl::reverseFromGeo($lat_long));
                            }

                        In der Funktionsreferenz des PHP-Kerns finden sich zahlreiche Funktionen, welche mixed Parameter akzeptieren. Das sehe ich als großen Vorteil von PHP. Warum soll dies nicht auch bei der OOP genutzt werden?
                        Man muss darauf zurückgreifen, weils in PHP derzeit keine vernünftigere Alternative gibt.
                        Wenn man die Wurst schräg anschneidet, hält sie länger, weil die Scheiben größer sind.

                        Kommentar


                        • #13
                          PHP-Code:
                          final class EmacsPHP
                          {
                              public function 
                          __construct(...$allTheThings)
                              {
                                  
                          // ...
                              
                          }

                          Kommentar


                          • #14
                            Noch eine Mini-Frage in dem Zusammenhang. Angenommen ich habe nur Exceptions definiert, mit denen ich den Typ prüfe, macht es dann überhaupt Sinn, wenn ich jedes mal, wenn ich ein Carbon-Objekt erzeuge, try-catch dazu schreibe? Denn die Exception wirft ja sowieso nen Fehler, und wenn ich den nicht berichtigt habe, geht gar nix. Hoffe das war verständlich.

                            PHP-Code:
                            <?php

                            try{
                               
                            $c = new Carbon();
                            }
                            catch(
                            Exception $e){
                               echo 
                            $e->getMessage();
                            }

                            //in anderer Datei

                            try{
                               
                            $c = new Carbon();
                            }
                            catch(
                            Exception $e){
                               echo 
                            $e->getMessage();
                            }

                            Kommentar


                            • #15
                              Hallöchen,

                              das kommt doch auf den jeweiligen Anwendungsfall an und wie du deinen Prozess geplant hast.

                              Viele Grüße,
                              lotti

                              Kommentar

                              Lädt...
                              X