schokoschabe: Optionale Argumente

Servus zusammen.

Habe mal wieder ein kleines Problem und suche Rat :)

Situation: Ich habe eine Klasse, an die 3 Paramater übergeben werden. Ich möchte 3 optionale Parameter hinzufügen.

Problem: Es ist durchaus möglich, das der Nutzer nur den 2. oder 3. optionalen Parameter nutzen möchte, nicht aber den 1.
Ich habe gelesen, wenn man den 2. Parameter angeben will, "muss" man auch alle vorherigen angeben. Ist das so richtig, und wenn ja, gibt es dazu keine Alternative?

Liebe Grüße,
Schokoschabe

  1. Mahlzeit schokoschabe,

    Ich habe gelesen, wenn man den 2. Parameter angeben will, "muss" man auch alle vorherigen angeben. Ist das so richtig,

    Ja.

    und wenn ja, gibt es dazu keine Alternative?

    Nein.

    MfG,
    EKKi

    --
    sh:( fo:| ch:? rl:( br:> n4:~ ie:% mo:} va:) de:] zu:) fl:{ ss:) ls:& js:|
    1. Ok, das war kurz und knapp.
      Werde dann nur einen optionalen Parameter hinzufügen.

      Lieben Dank für eure Antworten.

      Grüße

  2. Ich habe gelesen, wenn man den 2. Parameter angeben will, "muss" man auch alle vorherigen angeben. Ist das so richtig, und wenn ja, gibt es dazu keine Alternative?

    Mal logisch betrachtet, irgendwie muss sonst ja klar sein ob der eine übergebene Parameter der erste oder zweite sein soll.

    1. Hallo,

      Ich habe gelesen, wenn man den 2. Parameter angeben will, "muss" man auch alle vorherigen angeben. Ist das so richtig, und wenn ja, gibt es dazu keine Alternative?
      Mal logisch betrachtet, irgendwie muss sonst ja klar sein ob der eine übergebene Parameter der erste oder zweite sein soll.

      das Argument ist zwar nachvollziehbar; es gibt aber Programmiersprachen, die das hinkriegen. Dann folgt eben ein Komma in der Parameterliste direkt dem vorhergehenden, und der dazwischen vorgesehene Parameter fehlt. Als Pseudocode:

      function foo(x,y, optional p, optional q)
        { ...
          ...
          return (r)
        }

      foo(40, 21, 0.8, 1)       // Aufruf mit allen Parametern
       foo(40, 21)               // Aufruf mit Parametern x und y
       foo(40, 21,, 1)           // Aufruf mit Parametern x, y, und q

      Also möglich und syntaktisch einwandfrei ist das schon, aber es ist in PHP leider nicht so realisiert.

      Ciao,
       Martin

      --
      Abraham sprach zu Bebraham: Kann i mal dei Cebra ham?
  3. Hi,

    gibt es dazu keine Alternative?

    Du könntest nur einen optionalen Parameter vorsehen, der ein assoziatives Array ist.

    Cheatah

    --
    X-Self-Code: sh:( fo:} ch:~ rl:| br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
    X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
    X-Will-Answer-Email: No
    X-Please-Search-Archive-First: Absolutely Yes
  4. [latex]Mae  govannen![/latex]

    Situation: Ich habe eine Klasse, an die 3 Paramater übergeben werden. Ich möchte 3 optionale Parameter hinzufügen.

    Problem: Es ist durchaus möglich, das der Nutzer nur den 2. oder 3. optionalen Parameter nutzen möchte, nicht aber den 1.
    Ich habe gelesen, wenn man den 2. Parameter angeben will, "muss" man auch alle vorherigen angeben. Ist das so richtig, und wenn ja, gibt es dazu keine Alternative?

    Du könntest es vielleicht so machen, wie es auch in einigen PHP-Funktionen gelöst ist: Die nicht genutzen Parameter müssen mit einem bestimmten Wert befüllt werden, z.B. NULL. Innerhalb der Klasse kann man das dann abfragen (z.B. is_null) und die entsprechende Funktionalität freischalten/unterdrücken.

    Cü,

    Kai

    --
    A workaround for an avoidable problem often adds clutter and overhead to the program which
    could have been avoided by not creating the problem in the first place.(Garrett Smith/clj)
    Foren-Stylesheet Site Selfzeug JS-Lookup
    SelfCode: sh:( fo:| ch:? rl:( br:< n4:( ie:{ mo:| va:) js:| de:> zu:) fl:( ss:| ls:?
  5. Hallo,

    wenn Du sowieso schon im objektorientierten Kontext arbeitest, gibt es noch eine andere Möglichkeit. Hier musst Du nur entscheiden, ob das so in den Konzept passt.

    Mach aus den Variablen Eigenschaften der Klasse. Hier könnte es eben unlogisch werden, wenn es wirklich nur Parameter für den einzelnen Methodenaufruf sein sollen und nichts mit dem Klassenobjekt zu tun haben.

    Diese Eigenschaften würdest Du dann mit jeweils einer zugehörigen Methode DeineKlasse::setParameter1() setzen. Damit hättest Du volle Kontrolle über nicht gesetzte Eigenschaften.

    Deine Funktion greift dann auf diese Eigenschaften zurück und benötigen beim Aufruf keine Parameter mehr.

    Gruß, Thoralf

  6. Liebe schokoschabe,

    man kann ein assoziatives Array als Übergabeparameter benutzen und dann die Indices nach Belieben füllen...

    Liebe Grüße,

    Felix Riesterer.

    --
    ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
    1. Ich antworte mal hier aber für alle Antworter :)

      Wenn das ganze nur für meine private Nutzung wäre, wäre es sich kein Problem.
      Allerdings will ich die Klasse auch Leuten zur Verfügung stellen, die im schlimmstfall keine Ahnung von PHP haben. Es soll also mit so wenig Vorwissen wie möglich benutzbar sein.

      Die Klasse erstellt aus einem Text einen Farbverlauf.

      Als feste Parameter werden also übergeben:

      • $text
      • $startfarbe
      • $endfarbe

      Das funktioniert alles reibungslos.

      Ich wolle dem Nutzer aber die Möglichkeit geben, zusätzlich (so ursprünglich geplant)

      • eine weitere Farbe
      • eine Textgröße
      • und eine Font

      als optionale Parameter zu übergeben. Mit dem Wert "NULL" würde das für Normalanwender vllt eher umständlich, selbst wenn ich die Klasse mit detaillierten Erklärungen ausliefere.

      Hoffe ich habe mich einigermaßen verständlich gemacht :)

      1. Liebe Schokoschabe,

        Als feste Parameter werden also übergeben:

        • $text
        • $startfarbe
        • $endfarbe
        • eine weitere Farbe
        • eine Textgröße
        • und eine Font

        das ist alles kein Problem. Baue die Klasse in etwa so:

        class MeinSchriftBild {  
          
            var ersteEigenschaft;  
            var zweiteEigenschaft;  
          
            function MeinSchriftBild ($params) {  
                // Voreinstellungen  
                $parameter = array (  
                    'text'         => '',  
                    'startfarbe'   => '#ffffff',  
                    'endfarbe'     => '#000000',  
                    'weitereFarbe' => '#ff0000',  
                    'textgroesse'  => '12px',  
                    'font'         => 'Arial'  
                );  
          
                // übergebene Parameter übernehmen  
                foreach ($params as $key => $value) {  
                    if (array_key_exists($key, $parameter)) {  
                        // gültigen Parameter gefunden  
                        $parameter[$key] = $value;  
                    }  
                }  
          
                /* So, alle Parameter sind initialisiert  
                und eventuell mit übergebenen Werten belegt. */  
                tue_was();  
            }  
          
        }
        

        Liebe Grüße,

        Felix Riesterer.

        --
        ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
        1. Und wenn ich die startfarbe in RGB-Werte aufschlüsseln will, benutze ich dann z.b. einfach $parameter[1]?
          Wenn der Nutzer nebst den 3 geforderten Parametern als 4. Parameter aber die Font übergibt, landet das dann nicht in $parameter[4], dass eig die Textgröße enthalten sollte?

          Grüße

          1. Liebe Schokoschabe,

            Und wenn ich die startfarbe in RGB-Werte aufschlüsseln will, benutze ich dann z.b. einfach $parameter[1]?

            nein, sondern $parameter['startfarbe'].

            Wenn der Nutzer nebst den 3 geforderten Parametern als 4. Parameter aber die Font übergibt, landet das dann nicht in $parameter[4], dass eig die Textgröße enthalten sollte?

            Das Array benutzt keine Nummern, sondern Namen, um die Werte zu verwalten. Daher kann die Reihenfolge völlig vernachlässigt werden. $parameter['startfarbe'] ist immer der Wert, der im Aufruf mit dem "Namen" (man nennt das eigentlich Schlüssel) 'startfarbe' übergeben wurde, auch wenn die Reihenfolge der Indices nicht identisch sein sollte. Das ist der große Vorteil eines "assoziativen Arrays".

            Liebe Grüße,

            Felix Riesterer.

            --
            ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
            1. Ich muss mich eindeutig intensiver mit der Materie beschäftigen, wie es scheint.

              Kannst du mir anhand eines Beispiels das ganze erläutern?

              Wie genau würden die Parameter nun übergeben? Nehmen wir als Beispiel die 3 fixen Parameter und die Font.

              $gradient=new gradienttext("Farbverlauf","ffffff","000000","arial");  
              $gradient->creategradient();
              

              Die Font ("arial") würde automatisch in $parameter['font'] landen?

              LG

              1. Hallo

                Ich muss mich eindeutig intensiver mit der Materie beschäftigen, wie es scheint.

                Kannst du mir anhand eines Beispiels das ganze erläutern?

                Wie genau würden die Parameter nun übergeben? Nehmen wir als Beispiel die 3 fixen Parameter und die Font.

                $gradient=new gradienttext("Farbverlauf","ffffff","000000","arial");

                $gradient->creategradient();

                  
                ... würde zu  
                  
                ~~~php
                  
                $parameter['font'] = 'arial';  
                // bei noch mehr Parameterelementen z.B.  
                $parameter['groesse'] = '12';  
                $parameter['einheit'] = 'px';  
                  
                $gradient=new gradienttext("Farbverlauf","ffffff","000000",$parameter);  
                $gradient->creategradient();
                

                Das ginge natürlich auch so:

                $parameter = array(  
                'font'=>'arial',  
                'groesse'=>'12',  
                'einheit'=>'px');
                

                Stellt sich nur die Frage nach der bestmöglichen Lesbarkeit.

                Tschö, Auge

                --
                Verschiedene Glocken läuteten in der Stadt, und jede von ihnen vertrat eine ganz persönliche Meinung darüber, wann es Mitternacht war.
                Terry Pratchett, "Wachen! Wachen!"
                Veranstaltungsdatenbank Vdb 0.3
              2. Liebe Schokoschabe,

                $gradient=new gradienttext("Farbverlauf","ffffff","000000","arial");

                $gradient->creategradient();

                
                >   
                > Die Font ("arial") würde automatisch in $parameter['font'] landen?  
                  
                nein. Mein Ansatz war mit nur einem einzigen Parameter (siehe [mein vorheriges Posting](https://forum.selfhtml.org/?t=192392&m=1283949)!), der ein einziges assoziatives Array brauchte.  
                  
                ~~~php
                $gradient = new gradient(  
                    array(  
                        'text' => 'Farbverlauf',  
                        'startfarbe' => 'ffffff',  
                        'endfarbe' => '000000',  
                        'font' => 'arial'  
                    )  
                );  
                $gradient->creategradient();
                

                Liebe Grüße,

                Felix Riesterer.

                --
                ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
      2. Hi!

        Ich wolle dem Nutzer aber die Möglichkeit geben, zusätzlich (so ursprünglich geplant)

        • eine weitere Farbe
        • eine Textgröße
        • und eine Font
          als optionale Parameter zu übergeben.

        Kannst du diese Werte allein anhand ihres Inhalts auseinanderhalten? Eine Farbe wird ein sechsstelliger Hex-Wert (vielleicht mit vorangehendem #) sein. Die Textgröße eher ein Zahlenwert kleiner 100. Der Font wird ein String sein. Auf diese Gegebenheiten könntest du prüfen und damit quasi raten, was gemeint sein könnte. Allerdings könnte ein Farbwert auch ein String mit einem Namen sein, und den kannst du dann zumindest nicht mehr ganz so einfach vom Font-Namen unterscheiden. Andererseits sehe ich es als einfacher an, zu dokumentieren, dass null für einen nicht ausgefüllten optionalen Wert eingefügt werden muss, als diese doch im gewissen Umfang möglicherweise fehlinterpretierende Rateroutine zu implementieren.

        Lo!

        1. Den Farbwert vom Text zu unterscheiden wäre kein Problem, wenn ich den Farbwert mit dem # anfordere, was für Farbwerte natürlich wäre, und das dann filtere.
          Andererseits hast du vielleicht recht mit dem Ratespiel. Für den User möchte ich es nur so komfortabel wie möglich machen.

          Grüße :)

          Kannst du diese Werte allein anhand ihres Inhalts auseinanderhalten? Eine Farbe wird ein sechsstelliger Hex-Wert (vielleicht mit vorangehendem #) sein. Die Textgröße eher ein Zahlenwert kleiner 100. Der Font wird ein String sein. Auf diese Gegebenheiten könntest du prüfen und damit quasi raten, was gemeint sein könnte. Allerdings könnte ein Farbwert auch ein String mit einem Namen sein, und den kannst du dann zumindest nicht mehr ganz so einfach vom Font-Namen unterscheiden. Andererseits sehe ich es als einfacher an, zu dokumentieren, dass null für einen nicht ausgefüllten optionalen Wert eingefügt werden muss, als diese doch im gewissen Umfang möglicherweise fehlinterpretierende Rateroutine zu implementieren.

          Lo!

          1. Hi!

            Den Farbwert vom Text zu unterscheiden wäre kein Problem, wenn ich den Farbwert mit dem # anfordere, was für Farbwerte natürlich wäre, und das dann filtere.

            Das war nur ein Beispiel. Wenn du da mal in diese Richtung weiterdenkst, kommst du vielleicht auf die Idee, dass die Fontgröße nicht nur ein Zahlenwert sondern auch noch mit Einheit angegeben werden können soll, also 17pt, 21px, 2em, etc. Oder du willst noch andere Werte hinzufügen, die sich vom Typ oder Inhalt her nicht von den bisherigen unterscheiden lassen.

            Andererseits hast du vielleicht recht mit dem Ratespiel. Für den User möchte ich es nur so komfortabel wie möglich machen.

            Such einen Kompromiss! Der Anwender will es nicht nur vermeintlich einfach haben, es soll auch noch robust sein. In Python wäre das Problem schön lösbar, da kannst du benannte Parameter verwenden, und diese beliebig hinter den positionierten anordnen.

            fubar(pos1, pos2, pos3, key1 = foo, key3 = baz, key2 = bar)

            In PHP allerdings hast du so eine direkte Zuweisungsmöglichkeit nicht. Da kannst du nur positionierte Argumente übergeben.

            Die Entscheidung nun, ob du statt der positionierten Werte lieber ein Array entgegennimmst, solltest du gut gegeneinander abwägen. Die Syntax, um ein Array zu erstellen, ist nicht unbedingt einfacher als Argumente zu positionieren und "null"s einzufügen. Und letztlich sollte auch ein Anfänger bereits so viel gelernt haben, dass er weiß, wie eine Funktion aufzurufen ist, und dass die Reihenfolge der Parameter von Bedeutung ist.

            Meine Empfehlung: Mach es dir so (pflege)leicht wie möglich (sprich: positionierte Argumente mit "Auslassungs-null") und dokumentiere lieber eine Handvoll Aufrufbeispiele.

            Lo!

            1. Stimmt schon. Vielleicht sehe ich es problematischer als es ist. Vermutlich wird jmd ohne jedes Grundwissen nur selten nach PHP Klassen suchen um sie zu benutzen.

              Die Vorbelegung mit Nullwerten also... Ich werde das erstmal so umsetzen und meiner Freundin dann die Klasse zuschieben. Die hat von PHP keine Ahnung. Wenn die es versteht, ist alles i.O.

              Grüße

      3. Hi,

        Wenn das ganze nur für meine private Nutzung wäre, wäre es sich kein Problem.
        Allerdings will ich die Klasse auch Leuten zur Verfügung stellen, die im schlimmstfall keine Ahnung von PHP haben. Es soll also mit so wenig Vorwissen wie möglich benutzbar sein.

        Dieses Ziel anzustreben halte ich für wenig sinnvoll, wenn es "Klimmzüge" im Code erfordert, weil es mit normalen Sprachmitteln nicht umgesetzt werden kann.

        Parameter als name-wert-Paare in einem Array zu übergeben, ist gängige Praxis - insb. in Frameworks.

        MfG ChrisB

        --
        “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
      4. Hi Schokoschabe.

        Ich wolle dem Nutzer aber die Möglichkeit geben, zusätzlich (so ursprünglich geplant)

        • eine weitere Farbe
        • eine Textgröße
        • und eine Font

        als optionale Parameter zu übergeben.

        Ich empfehle aus praktischen und auch philosophischen Gruenden, drueber nachzudenken, ob diese Eigenschaften unbedingt als Parameter beim Erstellen des Objektes uebergeben werden sollen. Solche langen Parameterwuerste fuehren erstens dazu, dass man sich nix merken kann und jedes Mal in der Doku nachsehen muss, wenn man den Aufruf machen will, und zweitens zu den Problemchen, vor denen Du ja gerade stehst.

        Also wuerde ich vorschlagen: Der Konstruktor bekommnt nach wie vor die drei festen Parameter, und die Klasse kriegt Methoden wie

        • addColor
        • setFontSize
        • setFont

        Eine (sehr vage) Richtlinie dazu: Der Konstruktor ist (in erster Linie) dazu da, das Objekt zu initialisieren, also in einen vernuenftigen Anfangszustand zu bringen, in dem es existieren kann. Die Parameter, die man dem Konstruktor mitgibt, sind essentielle Informationen, die benoetigt werden, damit das Objekt ueberhaupt geboren werden kann.
        D.h.: Wenn - und so scheint es zu sein - das Objekt mit Default-Werten fuer Farbe, Groesse und Schriftart arbeiten kann, dann kann der Konstruktor prima auf diese Angaben verzichten.

        Das heisst nicht, dass sie im Konstruktor keine Daseinsberechtigung haben oder Dein Ansatz falsch ist, aber vielleicht ist diese Loesung handlicher und benuzterfreundlicher.

        Viele Gruesse,
        der Bademeister

        1. Wenn ich aber Methoden hinzufüge, die seperat Font, Fontsize und dritte Farbe erstellen, ist es für den Nutzer sicherlich einfacher, einfach selbst <font size... etc pp> Objektaufruf </font> zu machen.
          Ich wollte einfach alles komfortabel in einen Aufruf packen.
          Ob nun ein Objekt mit mindesten 3 und bis zu 6 Parametern komfortabel ist, bleibt tatsächlich zu bezweifeln.

          Im Moment ist es ganz simpel so:

          $gradient=new gradienttext("Farbverlauf","ffffff","000000");  
          $gradient->creategradient();
          

          Ich denke, das ist für jeden Laien in 2 Sätzen erklärt. Kopieren, einfügen, Werte ändern.

          Vllt verstehe ich dich aber auch falsch.

          Liebe Grüße

          1. Im Moment ist es ganz simpel so:

            $gradient=new gradienttext("Farbverlauf","ffffff","000000");

            $gradient->creategradient();

            
            >   
            > Ich denke, das ist für jeden Laien in 2 Sätzen erklärt. Kopieren, einfügen, Werte ändern.  
              
            Soweit ja. Wenn aber der naechste jetzt noch die Schriftgroesse aendern will, dann ist es - so oder so - mit Kopieren und Werte aendern nicht mehr getan. Dann muss er (in der Loesung mit den Parametern) im besten Fall sowas wie  
              
            ~~~php
            $gradient=new gradienttext("Farbverlauf","ffffff","000000", 12);  
            
            

            daraus machen, wenn, wie dedlfix schrieb, Du anhand der Werte erkennen kannst, welcher Parameter gemeint ist, und anderenfalls sowas wie

            $gradient=new gradienttext("Farbverlauf","ffffff","000000", null, 12);
            oder

            $gradient=new gradienttext("Farbverlauf","ffffff","000000", array("fontSize", 12));  
            
            

            Die Alternative waere

            $gradient=new gradienttext("Farbverlauf","ffffff","000000");  
              
            $gradient->setFontSize(12);  
            $gradient->creategradient();
            

            Ist ne Zeile mehr, klar. Aber in puncto Lesbarkeit und intuitiver Bedienung (kann man sich laenger als einen Tag merken, wie das mit dem Einstellen der Schriftgroesse noch gleich ging?), ist meine Meinung, was besser ist, relativ eindeutig.

            Viele Gruesse,
            der Bademeister

            1. Ok, so betrachtet ist es mit zusätzlich
              $gradient->setFontSize(12);
              sauberer/übersichtlicher.

              Ich werde mich aber mit allen Möglichkeiten auseinander setzen. Dann kann ich beim nächsten Mal vllt eher die passende Methode wählen.

              Liebe Grüße