Frage (OOP Zugriff auf andere Methoden)

09/27/2012 10:30 Greemt#1
Heyho liebe com.

Kurz und knapp, ich würde gerne von der einen Klasse auf die andere Zugreifen.
Ohne das die betroffene Methode statisch ist ( classxy::methodxy() ).
Würde mir da evtl jemand ein Hineweis geben wie ich das Regeln kann?
(hab öfters was von Singletons gehört, aber auch vieles gelesen was dagegen spricht.)

lg
09/27/2012 14:02 Mikesch01#2
PHP Code:
require_once('test2.class.php');

class 
Test {
  private 
$test2;

  public function 
__construct() {
    
$this->test2 = new Test2();
  }

  public function 
getTextinhalt() {
    return 
$this->test2->MethodeVonTest2();
  }
}

$test = new Test();
echo 
$test->getTextinhalt(); 
Nur ein Beispiel..du kannst es über eine Instanz in der Klasse versuchen
09/27/2012 14:18 Greemt#3
Mikesch, bitte lese dir erst den Post durch.
Evtl hast du meine Frage auch nicht verstanden.
Angenommen wir haben 2 Klasse, wie greif ich dabei von der einen auf die andere zu ohne die Funktionen Statisch belegen zu müssen.
Als bsp. mal in der Statischen Variante:

PHP Code:
class foo 
{
     static function 
xyz() {
          ......
     }
}
class 
bar {
     function 
xyz2() {
          
foo::xyz();
     }

So währe der Zugriff von der einen Klasse auf der anderen kein Problem, sobald jedoch ein $this-> vorkommt, haben wa nen kleines Problem.

lg
09/27/2012 14:26 マルコ#4
Du brauchst immer eine Instanz der Foo Klasse, wenn diese auf eine eigene Variable zugreifen soll, da diese Variable erst angelegt werden muss.
Du könntest aber eine Instanz der Foo Klasse per Konstruktor an die Bar Klasse übergeben...

Die Idee mit dem Singleton ist hier erklärt: [Only registered and activated users can see links. Click Here To Register...]
Das bedeutet, es gibt nur eine Instanz einer Klasse, und darauf kannst du theoretisch auch aus der 2. Klasse zugreifen.
Aber du brauchst immer ein Objekt, wenn du keine Statische Funktion hast.
09/27/2012 20:30 NotEnoughForYou#5
Quote:
Originally Posted by マルコ View Post
Du brauchst immer eine Instanz der Foo Klasse, wenn diese auf eine eigene Variable zugreifen soll, da diese Variable erst angelegt werden muss.
Du könntest aber eine Instanz der Foo Klasse per Konstruktor an die Bar Klasse übergeben...

Die Idee mit dem Singleton ist hier erklärt: [Only registered and activated users can see links. Click Here To Register...]
Das bedeutet, es gibt nur eine Instanz einer Klasse, und darauf kannst du theoretisch auch aus der 2. Klasse zugreifen.
Aber du brauchst immer ein Objekt, wenn du keine Statische Funktion hast.
oder man vererbt die Methoden ganz einfach.
09/29/2012 00:16 dowhile#6
Quote:
Originally Posted by NotEnoughForYou View Post
oder man vererbt die Methoden ganz einfach.
Angenommen wir haben eine Klasse "PersonViewer", die irgendwie Informationen zu einer Person anzeigt. Die Informationen bekommt die Klasse von einem Objekt von "PersonFinder", denn diese Klasse bietet folgende Methode: Person findPerson(String name). Das trifft dann, wenn ich die Eingangsfrage richtig verstanden haben, das "Problem" des TEs: Wie greift man in PersonViewer auf PersonFinder zu?

Wie genau darf ich jetzt deinen Vorschlag verstehen, NotEnoughForYou? Möchtest du PersonViewer "ganz einfach" von PersonFinder erben lassen, um Zugriff auf die Methode zu erhalten? Nur, wenn du das wirklich tun möchtest (ich denke eher, dass ich dich falsch verstanden haben): Wieso sollte ein PersonViewer ein PersonFinder sein? Welchen Sinn macht das? Ich denke, dass hier die anderen Lösungen definitiv sinnvoller sind.


Zum Thema: "Singleton" ist ein Design-Pattern (Entwurfsmuster), also eine generische Lösung auf ein häufiges Problem. Das Singleton Pattern wird eingesetzt, wenn es in der ganzen Applikation nur ein Objekt von einer Klasse geben darf und auf dieses eine Objekt von überall zugegriffen werden kann. Mit dem Singleton Pattern könnte sich eine displayPerson(String name) von PersonViewer in etwa so aussehen:

Code:
public void displayPerson(String name) {
  Person person = PersonFinder.getInstance().findPerson(name);
  // zeige person an
}
Damit hast du eine Lösung - je nach Situation aber keine besonders gute. Das große Problem am Singleton Pattern ist, dass du damit sehr starre Verbindungen zwischen Klasse schaffst.

a) Angenommen, du möchtest deine Applikation mit Unit-Tests testen. Dein PersonFinder findet die Personen in einer Datenbank. Wenn du also einen Test für PersonViewer schreiben möchtest, brauchst du eine entsprechende Datenbank und musst PersonFinder vor der Verwendung von PersonViewer entsprechend einrichten. Eigentlich aber möchtest du nur den PersonViewer testen, und in deiner Testumgebung ist es dir vollkommen egal, woher die Daten eigentlich stammen und ob diese irgendeinen Sinn ergeben. Du kannst die "Quelle" deiner Personen aber nicht austauschen, denn durch das Singleton Pattern ist dein PersonViewer fest an PersonFinder gebunden.

b) Nachdem du deine Anwendung fertig hast, stellt sich plötzlich die Anforderung, die Personen nicht mehr wie bisher aus einer Datenbank sondern von einem entfernten Server zu laden. Da PersonFinder fest in PersonViewer verankert ist, ist es dir nicht möglich, PersonFinder auszutauschen. Du musst also den Quelltext von PersonFinder verändern, um der neuen Anforderung gerecht zu werden. Damit brichst eine Regel des objektorientierten Entwurfs: Offen für Erweiterungen, geschlossen für Änderungen.


Wie kann man das Problem also besser lösen? Eine gute Lösung gab es schon, nämlich:
Quote:
Du könntest aber eine Instanz der Foo Klasse per Konstruktor an die Bar Klasse übergeben...
Angenommen, PersonFinder ist in Wirklichkeit nur ein Interface und wir verwenden zunächst DatabasePersonFinder, um Personen zu finden. Wenn wir dem PersonViewer einfach im Konstruktur einen PersonFinder übergeben, haben wir einige Vorteile hingegen der Singleton-Variante, dass wir jederzeit ohne große Änderungen einen anderen PersonFinder verwenden können. In unserer Testumgebung könnten wir dem PersonViewer beispielsweise einen TestPersonFinder übergeben, der immer die gleiche Person zurückgibt. Und wenn sich die Quelle der Personen im produktiven Einsatz ändert, können wir der neuen Anforderung mit einem neuen Finder sehr einfach zurecht werden.
Auch diese Vorgehensweise hat übrigens einen Namen, den du noch oft antreffen wirst, wenn du dich weiter mit OOP beschäftigst: DI (Dependency Injection) und IoC (Inverse of Control).

Dadurch, dass sich PersonViewer nicht mehr selbst um seine Abhängigkeiten kümmert, sondern die Abhängigkeiten von außen injiziert bekommt (-> DI; in der Praxis geschieht das bei größeren Projekten, wo Objekte oft von ganzen "Objektbäumen" abhängig sind, durch ein Framework, einem sogenannten DI Container), haben wir den normalen Kontrollfluss umgekehrt (-> Inverse of Control). Ein weiteres Beispiel für IoC ist z.B. auch die Ereignisorientierte Programmierung (Stichwort GUI-Systeme). In "klassischen" Programmen wird die Anwendung nach dem Start initialisiert und verfällt dann in eine Endlosschleife, in der geprüft wird, ob z.B. irgendwo hin geklickt wurde oder eine Taste gedrückt wurde. Bei "modernen" GUI-Systemen läuft das anders ab: Die Anwendung wird gestartet und initialisiert. Anschließend gibt das Programm die Kontrolle an das Framework / GUI-System ab. Über Ereignisse (Events) wird das Programm dann benachrichtigt, wenn es eine Interaktion o.ä. mit dem Programm gibt. Also wurde auch hier der normale Kontrollfluss umgedreht - nicht mehr das Programm ruft das Framework auf sondern das Framework das Programm -> IoC. Aber gut, das hat wohl nicht mehr viel mit der Frage zu tun ...
09/29/2012 10:21 NotEnoughForYou#7
Quote:
Originally Posted by dowhile View Post
Angenommen wir haben eine Klasse "PersonViewer", die irgendwie Informationen zu einer Person anzeigt. Die Informationen bekommt die Klasse von einem Objekt von "PersonFinder", denn diese Klasse bietet folgende Methode: Person findPerson(String name). Das trifft dann, wenn ich die Eingangsfrage richtig verstanden haben, das "Problem" des TEs: Wie greift man in PersonViewer auf PersonFinder zu?

Wie genau darf ich jetzt deinen Vorschlag verstehen, NotEnoughForYou? Möchtest du PersonViewer "ganz einfach" von PersonFinder erben lassen, um Zugriff auf die Methode zu erhalten? Nur, wenn du das wirklich tun möchtest (ich denke eher, dass ich dich falsch verstanden haben): Wieso sollte ein PersonViewer ein PersonFinder sein? Welchen Sinn macht das? Ich denke, dass hier die anderen Lösungen definitiv sinnvoller sind.


Zum Thema: "Singleton" ist ein Design-Pattern (Entwurfsmuster), also eine generische Lösung auf ein häufiges Problem. Das Singleton Pattern wird eingesetzt, wenn es in der ganzen Applikation nur ein Objekt von einer Klasse geben darf und auf dieses eine Objekt von überall zugegriffen werden kann. Mit dem Singleton Pattern könnte sich eine displayPerson(String name) von PersonViewer in etwa so aussehen:

Code:
public void displayPerson(String name) {
  Person person = PersonFinder.getInstance().findPerson(name);
  // zeige person an
}
Damit hast du eine Lösung - je nach Situation aber keine besonders gute. Das große Problem am Singleton Pattern ist, dass du damit sehr starre Verbindungen zwischen Klasse schaffst.

a) Angenommen, du möchtest deine Applikation mit Unit-Tests testen. Dein PersonFinder findet die Personen in einer Datenbank. Wenn du also einen Test für PersonViewer schreiben möchtest, brauchst du eine entsprechende Datenbank und musst PersonFinder vor der Verwendung von PersonViewer entsprechend einrichten. Eigentlich aber möchtest du nur den PersonViewer testen, und in deiner Testumgebung ist es dir vollkommen egal, woher die Daten eigentlich stammen und ob diese irgendeinen Sinn ergeben. Du kannst die "Quelle" deiner Personen aber nicht austauschen, denn durch das Singleton Pattern ist dein PersonViewer fest an PersonFinder gebunden.

b) Nachdem du deine Anwendung fertig hast, stellt sich plötzlich die Anforderung, die Personen nicht mehr wie bisher aus einer Datenbank sondern von einem entfernten Server zu laden. Da PersonFinder fest in PersonViewer verankert ist, ist es dir nicht möglich, PersonFinder auszutauschen. Du musst also den Quelltext von PersonFinder verändern, um der neuen Anforderung gerecht zu werden. Damit brichst eine Regel des objektorientierten Entwurfs: Offen für Erweiterungen, geschlossen für Änderungen.


Wie kann man das Problem also besser lösen? Eine gute Lösung gab es schon, nämlich:


Angenommen, PersonFinder ist in Wirklichkeit nur ein Interface und wir verwenden zunächst DatabasePersonFinder, um Personen zu finden. Wenn wir dem PersonViewer einfach im Konstruktur einen PersonFinder übergeben, haben wir einige Vorteile hingegen der Singleton-Variante, dass wir jederzeit ohne große Änderungen einen anderen PersonFinder verwenden können. In unserer Testumgebung könnten wir dem PersonViewer beispielsweise einen TestPersonFinder übergeben, der immer die gleiche Person zurückgibt. Und wenn sich die Quelle der Personen im produktiven Einsatz ändert, können wir der neuen Anforderung mit einem neuen Finder sehr einfach zurecht werden.
Auch diese Vorgehensweise hat übrigens einen Namen, den du noch oft antreffen wirst, wenn du dich weiter mit OOP beschäftigst: DI (Dependency Injection) und IoC (Inverse of Control).

Dadurch, dass sich PersonViewer nicht mehr selbst um seine Abhängigkeiten kümmert, sondern die Abhängigkeiten von außen injiziert bekommt (-> DI; in der Praxis geschieht das bei größeren Projekten, wo Objekte oft von ganzen "Objektbäumen" abhängig sind, durch ein Framework, einem sogenannten DI Container), haben wir den normalen Kontrollfluss umgekehrt (-> Inverse of Control). Ein weiteres Beispiel für IoC ist z.B. auch die Ereignisorientierte Programmierung (Stichwort GUI-Systeme). In "klassischen" Programmen wird die Anwendung nach dem Start initialisiert und verfällt dann in eine Endlosschleife, in der geprüft wird, ob z.B. irgendwo hin geklickt wurde oder eine Taste gedrückt wurde. Bei "modernen" GUI-Systemen läuft das anders ab: Die Anwendung wird gestartet und initialisiert. Anschließend gibt das Programm die Kontrolle an das Framework / GUI-System ab. Über Ereignisse (Events) wird das Programm dann benachrichtigt, wenn es eine Interaktion o.ä. mit dem Programm gibt. Also wurde auch hier der normale Kontrollfluss umgedreht - nicht mehr das Programm ruft das Framework auf sondern das Framework das Programm -> IoC. Aber gut, das hat wohl nicht mehr viel mit der Frage zu tun ...
Meine Antwort sollte lediglich die Moeglichkeit abdecken. Aus seinen Beispiel geht meiner Meinung naemlich nicht hervor, dass die beiden klassen nichts miteinander zu tun haben. Beu deinem Beispiel gebe ich dir natuerlich recht.