Jonathan
Jonathan

Reputation: 2837

Pass method as argument to Java method

I have some java code that I want to convert to Xtend. The Java code is:

public void createPartControl(Composite parent) {
    final Canvas clock = new Canvas(parent, SWT.None);
    clock.addPaintListener(this::drawClock);
}

private void drawClock(PaintEvent e) {
    e.gc.drawArc(e.x, e.y, e.width - 1, e.height - 1, 0, 360);
}

My attempt at Xtend code is:

override createPartControl(Composite parent) {
    val clock = new Canvas(parent, SWT.None);
    clock.addPaintListener(this::drawClock);
}

private def drawClock(PaintEvent e) {
    e.gc.drawArc(e.x, e.y, e.width - 1, e.height - 1, 0, 360);
}

The problem is that the expression this::drawClock is not valid in Xtend. Specifically it says that this cannot be resolved to a type. How do I achieve the same result using Xtend.

Upvotes: 2

Views: 184

Answers (1)

kapex
kapex

Reputation: 29949

Xtend doesn't support method references. You need to wrap the method you want to call in a Xtend lambda instead.

this::drawClock or (e) -> drawClock(e) in Java becomes [drawClock] in Xtend. The type is automatically inferred.

So you can write:

override createPartControl(Composite parent) {
    val clock = new Canvas(parent, SWT.None)
    clock.addPaintListener[drawClock]
}

The PaintEvent parameter of the listener is the implicit it parameter of the lambda. It is used automatically as first argument of drawClock. Parenthesis are optional for method calls with lambda arguments.

I would say the notation addPaintListener[drawClock] is the idiomatic, but you could of course also write this more explicit. All of these are equivalent:

clock.addPaintListener[drawClock]
clock.addPaintListener([drawClock])
clock.addPaintListener([drawClock(it)])
clock.addPaintListener([e|drawClock(e)])
clock.addPaintListener([PaintEvent e| e.drawClock])

If the method has multiple parameters, you can add those parameters to the lambda explicitly or use the implicit $1,$2,...,$n parameters, for example like this:

component.addFooListener[e1, e2| onFoo(e1, e2)]
component.addFooListener[onFoo($1, $2)]

Upvotes: 2

Related Questions