Classes and Members

At a first glance an Xtend file pretty much looks like a Java file. It starts with a package declaration followed by an import section and a class definition. The class in fact is directly translated to a Java class in the corresponding Java package. As in Java, a class can have constructors, fields and methods.

Here is an example:

package com.acme

import java.util.List

class MyClass {
  String name
  
  new(String name) {
    this.name = name
  }
  
  def String first(List<String> elements) {
    elements.get(0)
  }
}

Package Declaration

Package declarations are mostly like in Java. There are two small differences:

package com.acme

Imports

The ordinary imports of type names are equivalent to the imports known from Java. Again one can escape any names conflicting with keywords using a ^. In contrast to Java, the import statement is never terminated with a semicolon. Xtend also features static imports but allows only a wildcard * at the end, i.e. you cannot import single members using a static import. Non-static wildcard imports are deprecated for the benefit of better tooling.

As in Java all classes from the java.lang package are implicitly imported.

import java.math.BigDecimal
import static java.util.Collections.*

Static methods of helper classes can also be imported as extensions. See the section on extension methods for details.

Class Declaration

The class declaration reuses a lot of Java's syntax but still is a bit different in some aspects: Java's default "package private" visibility does not exist in Xtend. As an Xtend class is compiled to a top-level Java class and Java does not allow private or protected top-level classes any Xtend class is public. It is possible to write this explicitly.

Xtend's approach to inheritance is conceptionally the same as in Java. Single inheritance of Java classes as well as implementing multiple Java interfaces is supported. Because Xtend classes are compiled to Java, Xtend classes can extend other Xtend classes, and even Java classes can inherit from Xtend classes.

The most simple class looks like this:

class MyClass {
}

A more advanced class declaration in Xtend:

class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, 
                   Cloneable, java.io.Serializable {
  ...
}

Constructors

An Xtend class can define one or more constructors. Unlike Java, the keyword new is used to declare a constructor. Constructors can also delegate to other constructors using this(args...) in their first line.

class MyClass extends AnotherClass {
  new(String s) {
    super(s)
  }
  
  new() {
    this("default")
  }
}

The same rules with regard to inheritance apply as in Java, i.e. if the super class does not define a no-argument constructor, you have to explicitly call one using super(args...) as the first expression in the body of the constructor.

The default visibility of constructors is public but you can also specify protected or private.

Fields

An Xtend class can define fields, too. As for Java fields, you can optionally declare an initializer expression and use annotations on fields. Fields marked as static will be compiled to static Java fields.

class MyClass {
  @Nullable String name
  int count = 1
  String string = new String()
  static boolean debug = false
  ...
}

The default visibility is private. You can also declare it explicitly as being public, protected, or private.

A specialty of Xtend are fields that provide extension methods which are covered in their own section.

Methods

Xtend methods are declared within a class and are translated to a corresponding Java method with exactly the same signature. The only exceptions are dispatch methods, which are explained here.

def String first(List<String> elements) {
  elements.get(0);
}

The default visibility of a plain method is public. You can explicitly declare it as being public, protected, or private.

Xtend supports the static modifier for methods:

def static createInstance() {
  new MyClass('foo')
}

Overriding Methods

Methods can override other methods from the super class or implemented interface methods using the keyword override. If a method overrides a method from a super type, the override keyword is mandatory and replaces the keyword def. As in Java final methods cannot be overridden by subclasses.

Example:

override String first(List<String> elements) {
  elements.get(0);
}

Declared Exceptions

Xtend does not force you to catch checked exceptions. Instead, they are rethrown in a way the compiler does not complain about a missing throws clause, using the sneaky-throw technique introduced by Lombok. Nevertheless, you can still declare the exceptions thrown in a method's body using the same throws clause as in Java.

/*
 * throws an Exception
 */

def void throwException() throws Exception {
   throw new Exception()
}

/*
 * throws an Exception without declaring it
 */

def void sneakyThrowException() {
   throw new Exception()
}

Inferred Return Types

If the return type of a method can be inferred from its body it does not have to be declared. That is the method

def String first(List<String> elements) {
  elements.get(0);
}

could be declared like this:

def first(List<String> elements) {
  elements.get(0);
}

This does not work for abstract method declarations as well as if the return type of a method depends on a recursive call of the same method. The compiler tells the user when it needs to be specified.

Dispatch Methods

Generally, method binding works just like method binding in Java. Method calls are bound based on the static types of arguments. Sometimes this is not what you want. Especially in the context of extension methods you would like to have polymorphic behavior.

Dispatch methods make a set of overloaded methods polymorphic. That is the runtime types of all given arguments are used to decide which of the overloaded methods is being invoked. This essentially removes the need for the quite invasive visitor pattern.

A dispatch method is marked using the keyword dispatch.

def dispatch printType(Number x) { 
  "it's a number" 
}

def dispatch printType(Integer x) { 
  "it's an int" 
}

For a set of visible dispatch methods in the current type hierarchy, the compiler infers a common signature using the common super type of all declared arguments and generates a Java method made up of if instanceof else cascades. It dispatches to the different available methods. The actually declared methods are all compiled to Java methods that are prefixed with an underscore.

For the two dispatch methods in the example above the following Java code would be generated:

protected String _printType(final Number x) {
  return "it\'s a number";
}

protected String _printType(final Integer x) {
  return "it\'s an int";
}

public String printType(final Number x) {
  if (x instanceof Integer) {
    return _printType((Integer)x);
  } else {
    return _printType(x);
  }
}

Note that the instanceof cascade is ordered such that more specific types come first.

The default visibility of the underscore methods is protected. If all dispatch methods explicitly declare the same visibility, this will be the visibility of the inferred dispatcher, too. Otherwise it is public. In case there is no single most general signature, one is computed and the different overloaded methods are matched in the order they are declared within the class file. Example:

def dispatch printTypes(Number x, Integer y) { 
  "it's some number and an int" 
}

def dispatch printTypes(Integer x, Number y) { 
  "it's an int and a number" 
}

generates the following Java code :

public String printTypes(final Number x, final Number y) {
  if (x instanceof Integer) {
    return _printTypes((Integer)x, y);
  } else if (y instanceof Integer) {
    return _printTypes(x, (Integer)y);
  } else {
    throw new IllegalArgumentException("Unhandled parameter types: " +
      Arrays.<Object>asList(x, y).toString());
  }
}

As you can see a null reference is never a match. If you want to fetch null you can declare a parameter using the type java.lang.Void.

def dispatch printType(Number x) { 
  "it's some number" 
}

def dispatch printType(Integer x) { 
  "it's an int" 
}

def dispatch printType(Void x) { 
  "it's null" 
}

Which compiles to the following Java code:

public String printType(final Number x) {
  if (x instanceof Integer) {
    return _printType((Integer)x);
  } else if (x instanceof Number) {
    return _printType((Number)x);
  } else if (x == null) {
    return _printType((Void)null);
  } else {
    throw new IllegalArgumentException("Unhandled parameter types: " +
      Arrays.<Object>asList(x).toString());
  }
}

Dispatch Methods and Inheritance

Any visible Java methods from super types conforming to the compiled form of a dispatch method are also included in the dispatch. Conforming means they have the right number of arguments and have the same name (starting with an underscore).

For example, consider the following Java class :

public abstract class AbstractLabelProvider {
   protected String _label(Object o) {
      // some generic implementation
   }
}

and the following Xtend class which extends the Java class :

class MyLabelProvider extends AbstractLabelProvider {
   def dispatch label(Entity it)  {
     name
   }
     
   def dispatch label(Method it) { 
     name+"("+params.join(",")+"):"+type
   }
   
   def dispatch label(Field it) { 
     name+type
   }
}

The resulting dispatch method in the generated Java class MyLabelProvider would then look like this:

public String label(final Object it) {
  if (it instanceof Entity) {
    return _label((Entity)it);
  } else if (it instanceof Field) {
    return _label((Field)it);
  } else if (it instanceof Method) {
    return _label((Method)it);
  } else {
    return _label(it);
  }
}

Static Dispatch Methods

Even static dispatch methods are allowed. The same rules apply, but you cannot mix static and non-static dispatch methods.

Annotations

Xtend supports Java annotations. The syntax is exactly like defined in the Java Language Specification. Annotations are available on classes, fields, methods and parameters. Here is an example:

@TypeAnnotation(typeof(String))
class MyClass {
<<<<<<< HEAD   @FieldAnnotation(children = {@MyAnno(true), @MyAnno(false)})
  String myField
  
  @MethodAnnotation(children = {@MyAnno(true), @MyAnno})
=======   @FieldAnnotation(children = {@MyAnno(true), @MyAnno(false)}
  String myField
  
  @MethodAnnotation(children = {@MyAnno(true), @MyAnno}
>>>>>>> [xtend doc] regenerated   def String myMethod(@ParameterAnnotation String param) {
    //...
  }
}

Extension Methods

Extensions methods are a technique to add behavior to existing classes without modifying their code. This feature is actually where Xtend got its name from. They are based on a simple syntactic trick: Instead of passing the first argument of an extension method inside the parentheses of a call, the method is called on the argument parameter as if it was one of its members.

"hello".toFirstUpper() // calls toFirstUper("hello")

Method calls in extension syntax often result in much better readable code, as function calls are rather concatenated than nested. They also allow to add methods in a specific context only.

Local Extension Methods

All methods of the current Xtend class are automatically available in extension syntax. For example

class MyClass {
  def doSomething(Object obj) {
    // do something with obj
  }
  
  def extensionCall(Object obj) {
    obj.doSomething()  // calls this.doSomething(obj)
  }
}

Library Extensions

The static methods methods of the classes in the Xtend runtime library are automatically available as extensions, e.g.

newArrayList()       // CollectionLiterals.newArrayList()
"hello".toFirstUpper // StringExtensions.toFirstUpper(String)

Extension Imports

In Java, you would usually write a helper class with static methods to decorate an exisiting class with additional behavior. In order to integrate such static helper classes, Xtend allows to put the keyword extension after the static keyword of a static import thus making all imported static functions available as extensions methods.

The following import declaration

import static extension java.util.Collections.*

allows to use its methods like this:

new MyClass().singletonList() 
  // calls Collections.singletonList(new MyClass())

Although this is supported it is generally much nicer to use extension fields, because they allow to change the actual implementation easily.

Extension Fields

You can make the instance methods provided by the field available as extension methods, by adding the keyword extension to the field declaration.

Imagine you want to add a method fullName() to a closed type Person. With extension methods, you could declare the following class

class PersonExtensions {
  def getFullName(Person p) {
    p.forename + " " + p.name
  }
}

And if you have an instance of this class injected as extension like this:

class PersonPrinter {
  @Inject extension PersonExtensions
  ...
}

The method is available on the extension scope of the class Person. This is why you can skip the field's name. You can now write the following

def print(Person myPerson) {
  myPerson.getFullName()
}

which is translated to the Java method

public String print(final Person myPerson) {
  String _fullName = this._personExtensions.getFullName(myPerson);
  return _fullName;
}

where _personExtensions is the default name of the field. Of course the property shorthand (see section on property access) is still available.

myPerson.fullName

Using dependency injection in combination with the extension modifier has a significant advantage over to static extension imports: You can simply exchange the component that provides the referenced extension with another implementation without touching the client code. You will only have to change the binding in your dependency injection configuration. Also this gives you a general hook for any AOP-like thing you would want to do, or allows you to write against an SPI, where the concrete implementation can be provided by a third party.