Seite 1 von 1

Groovy: Ersatz für innere Klassen?!

Verfasst: 20.05.2008, 21:07
von stophi
Hallo zusammen,

Groovy unterstützt ja keine inneren Klassen. Stattdessen soll man Closures verwenden, so wie z.B. hier: http://glenp.net/articles/swing-events- ... y-closures
Das funktioniert mit Swing ActionListenern, aber ich verstehe nicht ganz, wie man das auf allgemeine Fälle übertragen kann (wenn das überhaupt geht).

Vielleicht kann mir das jemand an diesem Beispiel zeigen:

Code: Alles auswählen

new MyClass().copyToClipboard()
return 0    

public class MyClass {
    private text = "ugly code"

    // ...

    public void copyToClipboard(){
            def stringSelection = new java.awt.datatransfer.StringSelection( text )
            def clipboard = java.awt.Toolkit.getDefaultToolkit().getSystemClipboard()
            clipboard.setContents(stringSelection, new MyClipboardOwner()) // wie muss ich es ändern?
    }
}

private class MyClipboardOwner implements java.awt.datatransfer.ClipboardOwner {    
    void lostOwnership(java.awt.datatransfer.Clipboard clipboard, java.awt.datatransfer.Transferable transfer) {
        // do nothing
    }
}
Da es innere Klassen nicht gibt, muss ich die Klasse ausserhalb definieren, was ich irgendwie unschön finde.

Verfasst: 21.05.2008, 18:29
von panther
Das scheint eine Möglichkeit zu sein:

Code: Alles auswählen

public class MyClass {
    private text = "ugly code"

    // ...

    public void copyToClipboard(){
            def stringSelection = new java.awt.datatransfer.StringSelection( text )
            def clipboard = java.awt.Toolkit.getDefaultToolkit().getSystemClipboard()
            clipboard.setContents(stringSelection, this.&lostOwnership as java.awt.datatransfer.ClipboardOwner) // wie muss ich es ändern?
    }
    void lostOwnership(java.awt.datatransfer.Clipboard clipboard, java.awt.datatransfer.Transferable transfer) {
        // do nothing
    }
}

new MyClass().copyToClipboard()  

Verfasst: 21.05.2008, 18:42
von panther
Und so auch. Gleich als Closure in der Klasse definiert:

Code: Alles auswählen

public class MyClass {
    private text = "ugly code"

    // ...

    public void copyToClipboard(){
            def stringSelection = new java.awt.datatransfer.StringSelection( text )
            def clipboard = java.awt.Toolkit.getDefaultToolkit().getSystemClipboard()
            clipboard.setContents(stringSelection, this.lostOwnership as java.awt.datatransfer.ClipboardOwner) //mit und ohne '&' scheint es zu gehen
    }
    def lostOwnership = {clipboard, transfer ->
       println "verloren :("
    }
}

new MyClass().copyToClipboard() 

Verfasst: 21.05.2008, 22:58
von stophi
Super, danke :)

Groovy: Ersatz für innere Klassen?!

Verfasst: 26.05.2008, 13:49
von MichaelB
Hallo, ich habe mir das eben mal angeschaut und ein Ähnliches Problem.

Ich habe aber noch einen Konstruktor in meiner inneren Klasse.

Code: Alles auswählen

public class UmfragePage extends WebPage{
   private String wert
   
   public String getWert() {
	   return wert
   }
   public void setWert(String wert) {
	   this.wert = wert
   }
   
   public UmfragePage() {
	   Label bezeichnerLabel= new Label("bezeichner", new Model("Alter"))
	   TextField wertField= new TextField("wert", new PropertyModel(this,"wert"))
	   TextEingabeForm textEingabeForm= new TextEingabeForm("textEingabe")// dies möchte ich vermeiden!!

	   textEingabeForm.add(bezeichnerLabel)
	   textEingabeForm.add(wertField)
	   add(textEingabeForm)
   }
  
}
class TextEingabeForm extends Form {
	public TextEingabeForm(String id){
		super(id)
	}
	public void onSubmit(){
		setResponsePage(new ErgebnisPage(UmfragePage.this))
	}
	
}
Und nebenbei noch die frage, warum geht in Groovy eigentlich

Code: Alles auswählen

Umfrage.this 
in der TextEingabeKlasse nicht?

Gruß
Michael

Verfasst: 02.06.2008, 19:00
von stophi
Okay, ich kann es jetzt nicht testen, aber es könnte sein, dass es so (oder so ähnlich) funktioniert:

Code: Alles auswählen

public class UmfragePage extends WebPage{
   private String wert
   
   public String getWert() {
      return wert
   }
   public void setWert(String wert) {
      this.wert = wert
   }
   
   public UmfragePage() {
      Label bezeichnerLabel= new Label("bezeichner", new Model("Alter"))
      TextField wertField= new TextField("wert", new PropertyModel(this,"wert"))
      
      def textEingabeFormMethoden = [
        'onSubmit': { setResponsePage(new ErgebnisPage(owner))}
      ] 
      def textEingabeForm = ProxyGenerator.instantiateAggregateFromBaseClass(
          textEingabeFormMethoden, Form.class, "textEingabe")

      textEingabeForm.add(bezeichnerLabel)
      textEingabeForm.add(wertField)
      add(textEingabeForm)
   }
 
}
Mir ist allerdings nicht klar, wer der "owner" der closure nach 'onSubmit' ist. Wahrscheinlich ist das "textEingabeFormMethoden" und nicht "UmfragePage".
Vielleicht deshalb statt "owner" eben "this" schreiben, wobei ich mir nicht sicher bin, ob "this" dann "UmfragePage" oder "textEingabeForm" ist ...

Außerdem ... elegant finde ich diesen Syntax sowieso nicht. Da drücken innere Klassen klarer aus, was Sache ist.

http://groovy.codehaus.org/Groovy+Alter ... er+Classes

Verfasst: 03.06.2008, 09:39
von MichaelB
Hallo,
also ich habe das mal mit Probiert und mit this statt owner Funktioniert es! Allerdings mit einem Fehler auf der Konsole. Dort steht:

Code: Alles auswählen

java.io.NotSerializableException: jaxProjekt.UmfragePage$_closure1......
Das Original in Java sieht wie folgt aus:

Code: Alles auswählen

public class UmfragePage extends WebPage{
	private String wert;	
	public String getWert() {
		return wert;
	}
	public void setWert(String wert) {
		this.wert = wert;
	}
	public UmfragePage() {
		add(new MenuPanel("menu"));
		Form textEingabeForm=new Form("textEingabe") {
			@Override
			protected void onSubmit() {
				setResponsePage(new ErgebnisPage(UmfragePage.this));
			}
		};
		add(textEingabeForm);
		Label bezeichnerLabel=new Label("bezeichner",new Model("Alter"));
		textEingabeForm.add(bezeichnerLabel);
		TextField wertField=new TextField("wert",new PropertyModel(this,"wert"));
		textEingabeForm.add(wertField);		
	}
}
Deinen Groovy Inner Classes Link habe ich leider nicht so wirklich verstanden. Ist das was dort steht der ersatz für inner Classes?

Danke schonmal für die Anworten!

Gruß
Michael

Verfasst: 09.06.2008, 14:19
von stophi
Der Link ist ein Beispiel für den Ersatz für innere Klassen. Statt einen Haufen von Listener zu implementieren, wird in Groovy eben ein Objekt programmatisch zusammen gebaut. Also ich fand den Link sehr hilfreich zum Verständnis.

So wie das aussieht, musst du noch java.io.Serializable implementieren.
Mit Java geht das so:

Code: Alles auswählen

public class UmfragePage extends WebPage{
   private String wert;   
   public String getWert() {
      return wert;
   }
   public void setWert(String wert) {
      this.wert = wert;
   }
   public UmfragePage() {
      add(new MenuPanel("menu"));
      Form textEingabeForm=new TextEingabeForm();
      add(textEingabeForm);
      Label bezeichnerLabel=new Label("bezeichner",new Model("Alter"));
      textEingabeForm.add(bezeichnerLabel);
      TextField wertField=new TextField("wert",new PropertyModel(this,"wert"));
      textEingabeForm.add(wertField);      
   }
   
   private class TextEingabeForm extends Form implements Serializable {
       public TextEingabeForm() {
           super("textEingabe");
       }
       @Override
         protected void onSubmit() {
            setResponsePage(new ErgebnisPage(UmfragePage.this));
         }
   }
}
Wie das jetzt wieder in Groovy geht, weiß ich jetzt auch nicht. Schau halt mal, was der ProxyGenerator noch so an Möglichkeiten anbietet:
http://groovy.codehaus.org/gapi/groovy/ ... rator.html
Habe jetzt spontan nix gefunden, mit dem man von einer Klasse erben kann und gleichzeitig Interfaces implementieren kann. :?
Aber das geht bestimmt irgendwie.