Thomas: OOP-Einsteigerfragen

Hallo,

ich beschäftige mich gerade etwas mit OOP und habe das Prinzip auch einigermassen verstanden. Jetzt möchte ich von den Übungsbeispielen zu etwas praxisnäherem, da kommen dann aber schon die Probleme...

In kleineren Beispielen besteht das "Hauptprogramm" ausserhalb der Klassen immer nur aus ein paar Zeilen, in etwa:

$x  = new klasse();
print $x->dies();
print $x->das();

Kann das Hauptprogramm denn auch so aussehen, oder ist das dann nicht mehr so elegant (und wenn nicht, wie geht's anders):

$x  = new klasse();
if (irgendwas)
 {
  $x->mache_das();
 }
else
 {
  $x->mache_jenes();
 }

Und noch was: Wie mache ich es am besten mit globalen Einstellungen, die für das ganze Skript gelten sollen. Normalerweise würde ich das so machen:

$einstellung = [Wert];

function irgendwas()
{
 global $einstellung;
 ...
}

Schon mal Danke!
Thomas

  1. Hello Thomas,

    schau Dir mal http://tut.php-q.net/klassen.html an. Das ist zwar leider noch nicht so sehr lang, aber man versteht schon etwas mehr, als nur mit dem PHP-Manual.

    Harzliche Grüße aus http://www.annerschbarrich.de

    Tom

    --
    Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
    Nur selber lernen macht schlau
    1. Hi Tom,

      schau Dir mal http://tut.php-q.net/klassen.html an.

      Danke aber das kenne ich bereits. Dort ist das Hauptprogramm auch nur so:

      $x  = new klasse();
      print $x->dies();
      print $x->das();

      Angenommen ich möchte ein einfaches Gästebuch mit OOP machen. Ich hätte also eine Klasse, um die Einträge darzustellen und eine, um einen neuen Eintrag zu machen.

      Mein Skript sähe dann doch so aus:

      class Eintraege_anzeigen
       {
        ...
       }

      class neuer_Eintrag
       {
        ...
       }

      Jetzt muss ich das Ganze doch irgendwie im hauptprogramm steuern. Ich würde das jetzt so irgendwie machen, aber mir kommt das zu "konventionell" für OOP vor:

      if (empty($neuen_Eintrag_machen))
       {
        $Gaestebuch = new Eintraege_anzeigen;
       }
      else
       {
        $Gaestebuch = new neuer_Eintrag;
        $Gaestebuch->Formular_anzeigen();
       }

      Gruß,
      Thomas

      1. Hello,

        if (empty($neuen_Eintrag_machen))
         {
          $Gaestebuch = new Eintraege_anzeigen;
         }
        else
         {
          $Gaestebuch = new neuer_Eintrag;
          $Gaestebuch->Formular_anzeigen();
         }

        Ich sehe keinen Grund, warum Du sowas nicht tun dürftest. Natürlich stehen dir zur Programmsteuerung noch die Entscheidungsstrukturen, Schleifen etc zur Verfügung.

        Genial ist ea aber, wenn man Entscheidungsblöcke direkt auf einen Index abbilden kann, unter dem dann die passende Aktion liegt. Aber das hat ja schon vor ein paar Tagen Christian Seiler gezeigt, wie es richtig geht auch in der "klassischen" Programmierung.

        <?php   ### function_reference.php ###

        function show_string($arg)
        {
          echo "<p>Hallo $arg</p>";
        }
        #-------------------------------

        $text = 'show_string';
        $text ('so gehts richtig');

        $text ('und sogar zweimal');

        $_func = array();
        $_func[1] = 'show_string';

        $_func[1]('auch mit Arrays?');     ## dies ist eine "versteckte" Funktion
        $_func[1]('sogar mit Arrays!');

        ?>

        Das ist eigentlich schon frühe Objektorientierung, da man nun das Array mit den Funktionen einfach weitergeben (vererben) kann und dann einzelne davon einfach austauscht. Der Aufruf bleibt aber immer gleich. Leider muss man vorher trotzdem noch prüfen, ob der Index vorhanden ist, sonst gibt es einen Fehler.

        Aber Du erkennst vielleicht die Möglichkeiten. Du kannst den Eintscheidungswert nun direkt zum Index machen.

        Harzliche Grüße aus http://www.annerschbarrich.de

        Tom

        --
        Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
        Nur selber lernen macht schlau
        1. Hallo Tom,

          Ich sehe keinen Grund, warum Du sowas nicht tun dürftest. Natürlich stehen dir zur Programmsteuerung noch die Entscheidungsstrukturen, Schleifen etc zur Verfügung.

          OK, aber dann unterscheidet es sich doch kaum von nicht-OOP mit normalen Funktionen. Der Unterschied ist doch dann nur, dass ich mehrere Funktionen zu einer Klasse zusammenfassen kann und die Sache mit der Vererbung.

          Genial ist ea aber, wenn man Entscheidungsblöcke direkt auf einen Index abbilden kann, unter dem dann die passende Aktion liegt. Aber das hat ja schon vor ein paar Tagen Christian Seiler gezeigt, wie es richtig geht auch in der "klassischen" Programmierung.

          <?php   ### function_reference.php ###
          ...

          Hm, nett, aber wohl noch zu hoch für mich (obwohl ich's gerade noch so verstanden habe: im Prinzip einer Funktion variable Namen geben, oder?).

          Gruß
          Thomas

          1. Hi,

            OK, aber dann unterscheidet es sich doch kaum von nicht-OOP mit normalen Funktionen. Der Unterschied ist doch dann nur, dass ich mehrere Funktionen zu einer Klasse zusammenfassen kann und die Sache mit der Vererbung.

            IMHO ist ein Gästebuch auch keine klassische Anwendung für OOP, da ist das was zu tun ist einfach nicht so komplex, dass die Vorteile von OOP klar deutlich würden.

            <?php   ### function_reference.php ###
            ...

            Hm, nett, aber wohl noch zu hoch für mich (obwohl ich's gerade noch so verstanden habe: im Prinzip einer Funktion variable Namen geben, oder?).

            Nein, eine Funktion aufrufen, die den Namen trägt, dessen Inhalt die Variable _angibt_ ;-)

            Grüße aus Barsinghausen,
            Fabian

            1. Hello,

              Nein, eine Funktion aufrufen, die den Namen trägt, dessen Inhalt die Variable _angibt_ ;-)

              das  ist im Prinzip auch das, was man in OOP nutzt:

              $instanz->Funktion();

              ist im Prinzip nur eine andere Schreibweise für

              $instanz'Funktion';

              Der Vorteil der OOP bei PHP liegt in

              • Zusammenfassung von Funktionen in "Sinngruppen" == Klassen
                  Dadurch gibt es keine Namenskonflikte bei Hinzuladen unterschiedlicher "Librairies"
              • Kapselung von Funktionen in Klassen. Diese sind dann nur innerhalb der Klasse bekannt
              • Kapselung von Eigenschaften
              • Sehr leichte parallele Nutzung derselben Funktionen und der gleichen "Variablen"
                  durch die Instanzenbildung
              • man kann ein Script "einfrieren" indem man die Instanz im Status Quo abspeichert.
              • Man kann Programmteile "vorausentwickeln" = Prototyping, Abstrakte Klassen

              In 3rd Generation Languages (Pascal, C) war das aber auch in der klassischn prozeduralen Technik schon vor ca. 20 Jahren möglich... Und in Assembler gab es auch schon derartige Ansätze, nur nicht genügend Speicher.

              Die "echte" OOP ist eigentlich erst durch den Protected Mode der Prozessoren entstanden.

              PHP bildet diesen Schutz im Runtime nach.

              Harzliche Grüße aus http://www.annerschbarrich.de

              Tom

              --
              Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
              Nur selber lernen macht schlau
  2. Moin,

    [...]

    In kleineren Beispielen besteht das "Hauptprogramm" ausserhalb der Klassen immer nur aus ein paar Zeilen, in etwa:

    $x  = new klasse();
    print $x->dies();
    print $x->das();

    Kann das Hauptprogramm denn auch so aussehen, oder ist das dann nicht mehr so elegant (und wenn nicht, wie geht's anders):

    $x  = new klasse();
    if (irgendwas)
    {
      $x->mache_das();
    }
    else
    {
      $x->mache_jenes();
    }

    Selbstverständlich kannst du das machen. PHP ist keine reine OO Sprache.

    Und noch was: Wie mache ich es am besten mit globalen Einstellungen, die für das ganze Skript gelten sollen. Normalerweise würde ich das so machen:

    $einstellung = [Wert];

    function irgendwas()
    {
    global $einstellung;
    ...
    }

    Wenn sich der Wert zur Laufzeit nicht verändert, kannst du ihn als Konstante definieren. Ansonsten übergibtst du ihn der Methode, welche diesen voraussetzt. Oder du Übergibst ihn beim Instanzieren einer Klasse dem Konstruktor, welcher dafür sorgt, dass der Wert in einer Eigenschaft des Objektes gespeichert wird und somit für alle Methoden der Klasse und der abgeleiteten Klassen 'sichtbar' ist.

    Wenn du sicher stellen möchtest, dass das Objekt die Veränderungen des Wertes, welche an anderer Stelle stattfinden könnten, mitbekommt, übergibst du den Wert als Referenz.

    Auf 'global' _sollte_ man verzichten -- muss man aber nicht.

    --
    Gruss Martin
    1. moin,

      Wenn du sicher stellen möchtest, dass das Objekt die Veränderungen des Wertes, welche an anderer Stelle stattfinden könnten, mitbekommt, übergibst du den Wert als Referenz.

      ist das denn noch OOP-like?

      Auf 'global' _sollte_ man verzichten -- muss man aber nicht.

      warum?

      Gruß, Andreas

      --
      http://forum.andreas-lindig.de <img src="http://forum.andreas-lindig.de/bilder/logo.png" border="0" alt="">
      einfach mal testen und Meinung hinterlassen
      1. moin,

        Wenn du sicher stellen möchtest, dass das Objekt die Veränderungen des Wertes, welche an anderer Stelle stattfinden könnten, mitbekommt, übergibst du den Wert als Referenz.

        ist das denn noch OOP-like?

        Warum nicht? Wenn ein Objekt als Argument übergeben wird, wird dieser in anderen Sprachen implizit als Referenz übergeben (bei PHP 5 glaube ich auch). Einfache Datentypen werden grundsätzlich als Kopie übergeben. Es sei denn --wie schon beschrieben-- du möchtest, dass du an der einen Stelle mitbekommst, wenn an anderer Stelle etwas mit dem Wert geschehen ist. Der Effekt ist ein ähnlicher, wie bei globalen Variablen.

        Auf 'global' _sollte_ man verzichten -- muss man aber nicht.

        Ist nur eine Stilfrage. Und die Möglichkeiten, die dir OOP bietet, macht die Verwendung von globalen Variablen _grundsätzlich_ überflüssig. Globale Variablen sind bei größeren Projekten eine Fehlerquelle, welche nicht so einfach ausfindig zu machen ist.

        --
        Gruss Martin

        1. Hello,

          Warum nicht? Wenn ein Objekt als Argument übergeben wird, wird dieser in anderen Sprachen implizit als Referenz übergeben (bei PHP 5 glaube ich auch). Einfache Datentypen werden grundsätzlich als Kopie übergeben. Es sei denn --wie schon beschrieben-- du möchtest, dass du an der einen Stelle mitbekommst, wenn an anderer Stelle etwas mit dem Wert geschehen ist. Der Effekt ist ein ähnlicher, wie bei globalen Variablen.

          Nein, der Effekt ist ein ganz anderer. Ob ich ein Call by additonal Displacement (Konstante) oder ein Cal by Reference (variables Displacement, variabler Offset) durchführe, ist ein himmelweiter Unterschied. Der entscheidet nämlich über die Reentranzfähigkeit des Codes.

          Harzliche Grüße aus http://www.annerschbarrich.de

          Tom

          --
          Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
          Nur selber lernen macht schlau
          1. Hello,

            [...] Einfache Datentypen werden grundsätzlich als Kopie übergeben. Es sei denn --wie schon beschrieben-- du möchtest, dass du an der einen Stelle mitbekommst, wenn an anderer Stelle etwas mit dem Wert geschehen ist. Der Effekt ist ein ähnlicher, wie bei globalen Variablen.

            Nein, der Effekt ist ein ganz anderer. Ob ich ein Call by additonal Displacement (Konstante) oder ein Cal by Reference (variables Displacement, variabler Offset) durchführe, ist ein himmelweiter Unterschied. Der entscheidet nämlich über die Reentranzfähigkeit des Codes.

            Fall 1.:

            -----------------------------------------------
            class A
            {
                var $Ref = '';

            function A( & $ref )
                {
                    $this->Ref =& $ref;
                }

            }

            $x = 'foo';
            $obj = new A( $x );
            print_r( $obj->Ref );
            echo "\n";
            $x = 'bar';
            print_r( $obj->Ref );
            echo "\n";
            -----------------------------------------------

            Hier hat die Eigenschaft Ref erstmal den Wert 'foo' und dann 'bar'.

            Fall 2:
            ----------------------------------------------
            class B
            {
                var $Ref = '';

            function B( )
                {
                    global $x;
                    $this->Ref =& $x;
                }
            }

            $x = 'foo';
            $obj = new B( );
            echo $obj->Ref, "\n";
            $x = 'bar';
            echo $obj->Ref, "\n";
            ----------------------------------------------
            Hier hat die Konstante Ref ebenfalls erst den Wert 'foo' und dann 'bar'.

            --
            Gruss Martin
            1. Hello,

              ich kenne den Unterschied. Ich musste mich lange genug mit DOS abmühen, wo der Fall 2 leider häufig programmiert worden war.

              Fall 2 lässt sich nur mit $x verweden.
              Fall 1 lässt sich mit jeder beliebigen Referenz benutzen und ist daher auch in der Lage rekursiv oder reentrant eingesetzt zu werden, also von zwei Applikationen "gleichzeitig" genutzt zu werden.

              Harzliche Grüße aus http://www.annerschbarrich.de

              Tom

              --
              Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
              Nur selber lernen macht schlau
              1. Moin,

                ich kenne den Unterschied. Ich musste mich lange genug mit DOS abmühen, wo der Fall 2 leider häufig programmiert worden war.

                Fall 2 lässt sich nur mit $x verweden.
                Fall 1 lässt sich mit jeder beliebigen Referenz benutzen und ist daher auch in der Lage rekursiv oder reentrant eingesetzt zu werden, also von zwei Applikationen "gleichzeitig" genutzt zu werden.

                Deswegen hat die Benutzung von Referenzen "einen ähnlichen Effekt" auf das Ergebnis (hier die Eigenschaft aus dem Beispiel Ref), wie die Benutzung von 'global'. Und warum man auf 'global' verzichten soll, hast du ja ansatzweise schon geschrieben bzw. angedeutet. (Es wurde ja weiter oben im Thread gefragt, warum man auf global verzichten soll.)

                --
                Gruss Martin
  3. In kleineren Beispielen besteht das "Hauptprogramm" ausserhalb der Klassen immer nur aus ein paar Zeilen, in etwa:

    $x  = new klasse();
    print $x->dies();
    print $x->das();

    Kann das Hauptprogramm denn auch so aussehen, oder ist das dann nicht mehr so elegant (und wenn nicht, wie geht's anders):

    $x  = new klasse();
    if (irgendwas)
     {
      $x->mache_das();
     }
    else
     {
      $x->mache_jenes();
     }

    warum nicht ? du rufst verschiedene methoden in abhängigkeit auf.
    (laß dich nicht verwirren, aber solche konstrukte sollen durch oop auch vermieden werden. ist am anfang nicht so wichtig. bei genügend übung wirst du das später selbst herausfinden. allerdings ist das in php noch nicht sprachlich implementiert, und muß 'von hand' in den klassen berücksichtigt werden. stichwort signaturen.)

    Und noch was: Wie mache ich es am besten mit globalen Einstellungen, die für das ganze Skript gelten sollen. Normalerweise würde ich das so machen:

    $einstellung = [Wert];

    function irgendwas()
    {
     global $einstellung;
     ...
    }

    nicht gegen 'globale' information. manchmal sehr hilfreich und geschickt. schränkt aber den gedanken der unabhängigen wiederverwendung ein.
    wenn deine klassen eh nur für ein bestimmtes projekt gelten, kein problem. wenn du aber universelle klassen möchtest, mußt du die sichtbarkeit auf die reine kapselung legen. also jeden informationsaustausch außerhalb von methodenaufrufen oder öffentlichen attributsänderungen verhindern.

    aber es scheint mir, als ob du für dein gästebuch 'Darstellungsklassen' erstellst. das ist auch eine feine sache.

    aber in erster linie solltest du klassen für die logik erstellen.
    denk doch mal an eine klasse 'eintrag', welche alle dinge für einen eintrag behandelt (prüfungen, speicherung ..)

    1. Hello,

      warum nicht ? du rufst verschiedene methoden in abhängigkeit auf.
      (laß dich nicht verwirren, aber solche konstrukte sollen durch oop auch vermieden werden. ist am anfang nicht so wichtig. bei genügend übung wirst du das später selbst herausfinden. allerdings ist das in php noch nicht sprachlich implementiert, und muß 'von hand' in den klassen berücksichtigt werden. stichwort signaturen.)

      Da ich noch kein wirklich gutes Tut zu OOP gefunden habe...
      Könntest Du bitte noch etwas tiefer auf die Signaturen eingehen und mal ein "klitzekleines" Beispiel bringen? Das würde meine Sammlung um einweiteres Element vervollständigen.

      Harzliche Grüße aus http://www.annerschbarrich.de

      Tom

      --
      Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
      Nur selber lernen macht schlau
      1. jou, können wir.

        wie dir sicherlich aus java bekannt ist, können methodendeklarationen in einer klasse mehrfach mit unterschiedlichen argumenten erfolgen. die argumente können sich in anzahl und typ unterscheiden. (signatur)

        hieraus ergibt sich die folge, daß fallunterscheidungen nicht explizit erfolgen müssen (if, case), weil dies in der signatur möglich ist.

        in php werden signaturen noch nicht unterstützt.
        es gibt aber funktionen, um die übergebenen argumente auf anzahl und typ zu bestimmen. dies muß dann immer zuerst in einer öffentlichen methodendeklaration erfolgen, und dann die entsprechende private methode gerufen werden.

        gruß aus derzeit wob, sonst bs

        1. jou, können wir.

          wie dir sicherlich aus java bekannt ist, können methodendeklarationen in einer klasse mehrfach mit unterschiedlichen argumenten erfolgen. die argumente können sich in anzahl und typ unterscheiden. (signatur)

          hieraus ergibt sich die folge, daß fallunterscheidungen nicht explizit erfolgen müssen (if, case), weil dies in der signatur möglich ist.

          in php werden signaturen noch nicht unterstützt.

          Ich glaube nicht, dass Signaturen irgend wann mal in PHP Unterstützung finden. Dafür müsste PHP zu Variablendeklarationen mit Typangaben verpflichten.

          [...]

          --
          Gruss Martin
          1. Ich glaube nicht, dass Signaturen irgend wann mal in PHP Unterstützung finden. Dafür müsste PHP zu Variablendeklarationen mit Typangaben verpflichten.

            schon recht, aber computer können halt nur native datentypen. von daher wäre es ja denkbar, die implizite typumwandlung in php durch optionale explizite typangaben zu erweitern. würde bei diesen natürlich erst einmal massenhafte exeptions erzeugen. denkbar wäre ja auch ein explizites typcasting bei methodenaufrufen.
            und in den methodendeklarationen unterstützung durch ein neues schlüsselwort 'signatur', welches signaturen behandelt, damit man das nicht immer 'von hand' machen muß.

            aber was spricht grundsätzlich dagegen, auch in php die mehrfachdeklaration von methoden mit unterschiedlichen signaturen zu implementieren. wer das nicht nutzt merkt ja nix davon. der interpreter hätte zwar etwas mehr zu tun, aber die cpus werden ja auch immer schneller.

            ich halte das nicht für unmöglich.