# Eine Instanz übergeben ohne sie neu zu bilden



## m!k3 (20. Sep 2004)

Hi,

ich habe mal wieda ein Problem und weiß absolut nicht wie ich dieses lösen könnte.

Bei meinem Chat habe ich jetzt drei Java-Dateien (sprich 3 Klassen)

LoginFrame
ChatFrame
Chatclient ( Client - Server Logik )

nun wenn Chatclient gestartet wird, wird der LoginFrame aufgerufen, sprich eine neue Instanz davon gemacht.
Wird jetzt beim LoginFrame der "Anmeldebutton" gedrückt, muss sich der Client mit dem Server verbinden über die Klasse Chatclient, die ich aber nicht neue bilden kann, weil sonst wieder ein LoginFrame entstehen würde.

Gleiche Probleme hab ich beim Chatframe (z.B. Schließen ( was heisst ich muss mich beim Server abmelden über Chatclient, oder einfach einen Post schreiben - läuft ja auch über Chatclient ))

Eine Idee wäre natürlich die komplette Action Verarbeitung an Chatclient zu übergeben - hatte ich schon - find ich aber eine total blöde Lösung, weil ich Komponenten doppelt anlegen muss, und mir die Komponenten von LoginFrame bzw. ChatFrame holen muss um sie zu verarbeiten. Unsinnig..

Oder weiß jemand noch eine bessere Lösung?!


----------



## foobar (20. Sep 2004)

Ich würde das so lösen:
- LoginFrame wird aufgerufen
- Benutzer logged sich ein
- LoginFrame erstellt einen neuen ChatFrame und macht diesen sichtbar
- ChatFrame erstellt eine Instanz von ChatClient und speichert diese in einer Membervariablen
- ChatFrame kommuniziert mit Hilfe von ChatClient mit dem Server
......

HTH


----------



## m!k3 (20. Sep 2004)

hi foobar,

ja so ähnlich hab ichs ja.. nur ich muss auch von LoginFrame Chatclient aufrufen, weil ich passwort vom server abfragen muss für den login... und user und sowas..

ähm.. ich hab jetzt ne eigene methode gemacht für den Start des LoginFrames bei der Klasse Chatclient

Nun kann ich Chatclient immer neu instanzieren... nuuuur... ich krieg Probleme mit meinem PrintStream 

der PrintStream wird erstellt, wenn ich den Anmeldebutton im LoginFrame drücke. Da wird die Connection zum Server aufgebaut ( brauch ich ja wie oben schon gesagt wegen User und Passwortabfrage ).

Nun wenn ich dann den Chatframe starte ( von Chatclient aus, weil ich dort PW und User überprüfe ) muss ich im Chatframe nochmals eine Instanz von Chatclient machen und mein PrintStream is weg !

shice..  :cry:


----------



## m!k3 (20. Sep 2004)

also es gibt schon ne Lösung.. aber das find ich total besch....

wenn ich eine Instanz von ChatFrame in Chatclient mache übergebe ich den aktuellen PrintStream

eine Methode setPrintStream in Chatclient setzt dann den PrintStream von ChatFrame aus, da ich diesen ja dorthin übergeben habe.

also ich finds schlecht.. 

ne andere Komplettlösung die ganze Funktionalität in Chatclient zu gestalten finde ich umständlich und auch nicht schön, weil ich Komponenten hin und her übergebe..


----------



## dotlens (20. Sep 2004)

kannst du nicht mit einerer referenz arbeiten? oder hab ich das irgendwie falsch verstanden?


----------



## m!k3 (20. Sep 2004)

referenz?!  ???:L


----------



## m!k3 (20. Sep 2004)

sprich Instanz clonen und als Object übergeben?!


----------



## foobar (20. Sep 2004)

Du könntest ChatClient als Singleton implementieren, dann kannst du von überall auf diese selbe Instanz zugreifen.


----------



## m!k3 (20. Sep 2004)

ähm und wie macht man sowas?..


----------



## m!k3 (20. Sep 2004)

```
public class Chatclient extends Thread
{
    public static Chatclient client = null;

    public Chatclient()
    {
         new LoginFrame();
    }

    public static Chatclient getInstance()
    {
        return client;
    }
    
    public void meineMethode()
    {
        System.out.println("Bin drin");
    }

    public static void main(String[] args)
    {
        client = new Chatclient();
    }
}
```



```
public class LoginFrame
{
    public LoginFrame()
    {
         Chatclient.getInstance().meineMethode();    
    }
}
```
so müsste das dann wohl funktioniert hm?!  :roll:

edit:

so kann ich mir dann die Instanz holen und auf alle Methoden zugreifen.. das ja spitze )
sowas gefällt mir *g


----------



## Pulvertoastman (20. Sep 2004)

m!k3 hat gesagt.:
			
		

> so kann ich mir dann die Instanz holen und auf alle Methoden zugreifen.. das ja spitze )
> sowas gefällt mir *g



Mir nicht!

http://c2.com/cgi/wiki?SingletonGlobalProblems

Am übelsten finde ich an dieser Lösung noch, dass es sich um ein Singleton mit public Konstruktor handelt.


----------



## foobar (20. Sep 2004)

So sollte dein Singleton aussehen:

```
public class Chatclient extends Thread
{
    private static Chatclient client = null;
    private Chatclient()
    {
         // mach irgendwas
    }

    public static Chatclient getInstance()
    {
        if (client == null)
         {
             client = new Chatclient();
         }
         return client;
    }
   
    public void meineMethode()
    {
        System.out.println("Bin drin");
    }

    public static void main(String[] args)
    {
        ChatClient.getInstance().meineMethode();
    }
}
```


----------



## m!k3 (20. Sep 2004)

mhh joa hab mitgekriegt, dass wenn ich einfach eine Methode public static deklarier.. ich auch von andren Klassen zugreifen kann ohne die Instance zu holen...

wird das dann mit private nicht mehr gehn oder?

also:
private Chatclient()


----------



## foobar (20. Sep 2004)

> wird das dann mit private nicht mehr gehn oder?


Jepp, private Methoden respektive Member sind nur in der eigenen Klasse sichtbar.


----------



## m!k3 (20. Sep 2004)

warum macht man denn überhaupt so einen Singleton?

könnt doch meine Methode public static machen und so drauf zugreifen ohne ne Instanz zu holen... 

mhh.. naja da wird dann wohl Chatclient auch public sein müssen.. drum gefällt das Pulvertoastman wohl ned *g


edit:

aber warum gibts public, wenns doch mit Singleton gelöst werden soll..?!.. wieso mach ich dann überhaupt mein Objekt public?!.. 
kann mir irgendjemand vor und nachteile sagen oder so?!


----------



## Pulvertoastman (20. Sep 2004)

Wenn du nurr den Konstruktor privat emachst, heisst das lediglich, dass du von ausserhalb der Klasse keine Instanz dieser Klasse mehr erzeugen kannst. Der Zugriff auf die Methoden bleibt davon unbeeindruckt.

Nebenbei: Ich befürchte, dass du dazu tendierst, alle Methoden public static zu machen. Das ist zwar toll, wenn du dir damit ersparen willst, Instanzen der Objekte zu erstellen, hat aber mit OOP weniger zu tun.


----------



## m!k3 (20. Sep 2004)

nee ich habs jetzt so gemacht wie foobar des geschrieben hat.. hab überall nur noch priv.. das einzige was static ist.. ist des getInstance() und das muss ja auch nur static sein, damit ich es in der main methode aufrufen kann, sehe ich das richtig?! 

warum gibts public static dann überhaupt?!.. okay.. für variablen.. damit ich die inhalte in jeder methode habe.. wenn ich nen scheiss laber bitte korrigieren


----------



## m!k3 (20. Sep 2004)

wieso lande ich hier in einer Endlosschleife?! bzw. ende im Überlauf


```
public class Klasse1 {
    
    /** Creates a new instance of Klasse1 */
    private static Klasse1 class1 = null; 
    private Klasse1() 
    { 
        Klasse2 class2 = new Klasse2();
    } 

    public static Klasse1 getInstance() 
    { 
        if (class1 == null) 
         { 
             class1 = new Klasse1(); 
         } 
         return class1; 
    } 
    
    public void meineMethode() 
    { 
        System.out.println("Bin drin"); 
    } 

    public static void main(String[] args) 
    { 
        Klasse1.getInstance(); 
    } 
}
```


```
public class Klasse2 {
    
    //private Klasse1 class1 = null;
    /** Creates a new instance of Klasse2 */
    public Klasse2() {
        //class1 = Klasse1.getInstance();
        this.runMethode();
    }
    
    public void runMethode()
    {
        //class1.meineMethode();
        Klasse1.getInstance().meineMethode();
    }
}
```


----------



## m!k3 (20. Sep 2004)

class1 bleibt immer null... wieso?!...


----------



## m!k3 (20. Sep 2004)

okay.. das objekt wird neu gebildet.. folglich macht er auch das hier:


private static Klasse1 class1 = null; 

somit ist class1 = null;

mhhh.. aber ich hab ne ähnliche konstillation bei Chatclient.. und da gehts..

weil wenn sich der Client mit dem Server verbinden muss wird bei der Klasse Chatclient ein connect durchgeführt den ich so aufrufe:


```
Chatclient.getInstance().connect( ... );
```

das funktioniert..

ruf ich allerdings den connect so auf:


```
client = Chatclient.getInstance();

client.connect( ... );
```
habe ich wieder eine Endlosschleife... ich blick nicht mehr durch..  :cry:


Kann es sein das solch ein Singleton nur bei Thread-abhängigen Klassen funktioniert?

Weil ich starte ja nach dem Connect einen Thread... und somit ist Chatclient nicht mehr null.. jedenfalls steht was mit Thread drin..


----------



## foobar (20. Sep 2004)

Im Konstruktor von Klasse1 erzeugst du eine neue Instanz von Klasse2. In Klasse2 rufst du die Methode runMethod auf, die wiederum eine Instanz von Klasse1 erzeugt. Da du aber den ersten Konstruktoraufruf von Klasse1 noch nicht beendet hast, endet das ganze in einem Stackoverflow.


----------



## m!k3 (20. Sep 2004)

ahhh... jetzt checks ich.. ich muss den Konstruktoraufruf beenden.. boah.. thxx


----------

