Groovy: Ersatz für innere Klassen?!

Java und die Scriptsprachen (z.B. Groovy usw...)

Moderator: wegus

Antworten
Benutzeravatar
stophi
Beiträge: 150
Registriert: 02.03.2007, 07:32
Wohnort: München
Kontaktdaten:

Groovy: Ersatz für innere Klassen?!

Beitrag von stophi » 20.05.2008, 21:07

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.

Benutzeravatar
panther
Beiträge: 464
Registriert: 30.06.2006, 20:32
Kontaktdaten:

Beitrag von panther » 21.05.2008, 18:29

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()  

Benutzeravatar
panther
Beiträge: 464
Registriert: 30.06.2006, 20:32
Kontaktdaten:

Beitrag von panther » 21.05.2008, 18:42

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() 

Benutzeravatar
stophi
Beiträge: 150
Registriert: 02.03.2007, 07:32
Wohnort: München
Kontaktdaten:

Beitrag von stophi » 21.05.2008, 22:58

Super, danke :)

MichaelB

Groovy: Ersatz für innere Klassen?!

Beitrag von MichaelB » 26.05.2008, 13:49

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

Benutzeravatar
stophi
Beiträge: 150
Registriert: 02.03.2007, 07:32
Wohnort: München
Kontaktdaten:

Beitrag von stophi » 02.06.2008, 19:00

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

MichaelB

Beitrag von MichaelB » 03.06.2008, 09:39

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

Benutzeravatar
stophi
Beiträge: 150
Registriert: 02.03.2007, 07:32
Wohnort: München
Kontaktdaten:

Beitrag von stophi » 09.06.2008, 14:19

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.

Antworten