Professional Documents
Culture Documents
http://www.eclipse.org/Xtext/xtend/#download
1 of 8
11/10/2011 10:55 PM
Eclipse Xtend
http://www.eclipse.org/Xtext/xtend/#download
Download
You need a running Eclipse including the Java Development Tools (JDT). To install the Xtend plugins open the update manager and paste one of the URLs on the right into the field 'Work with' and select the Xtend SDK.
Tutorial
If you want to get your hands on it, we recommend to materialize the tutorial example using Eclipse's example wizard. To do so in the IDE click:
FILE
Documentation
You might want to have a look at what's on this page first. To get more detailed information about the various languae features you can have a look at the reference documentation. In addition to the pdf version it's also included in Xtext's html documentation.
The project consists of a bunch of Xtend files. Each of them illustrates a certain language feature and they are named accordingly. Those sample files contain a lot of working code snippets with some explanation in the comments. Just try it, it's straight forward.
2 of 8
11/10/2011 10:55 PM
Eclipse Xtend
http://www.eclipse.org/Xtext/xtend/#download
3 of 8
11/10/2011 10:55 PM
Eclipse Xtend
http://www.eclipse.org/Xtext/xtend/#download
annotation types.
4 of 8
11/10/2011 10:55 PM
Eclipse Xtend
http://www.eclipse.org/Xtext/xtend/#download
Variable Declarations
val names = getTheListOfNames() val List<String> names = getTheListOfNames()
For-Loops
for (name : getTheListOfNames()) // do something with name for (String name : getTheListOfNames()) // do something with name
It's sometimes a good idea to write the type nevertheless, but most of the time it's just redundant noise and distracting the reader. Xtend doesn't force you to write the type everywhere, but you still can, if you want.
Return types
def getTheListOfNames() { newArrayList("Tomte","Pippi","Carlson") } def List<String> getTheListOfNames() { newArrayList("Tomte","Pippi","Carlson") }
Closures
getTheListOfNames().map( name | "Mr. "+name ) getTheListOfNames().map( String name | "Mr. "+name )
Optionality
Parenthesis for method invocations are optional, if the method does not take any arguments.
obj.compute
instead of
person.getName()
instead of
obj.compute()
Semicolons are optional and even the return keyword doesn't need to be specified. The result of the last expression in a method definition is treated as the implicit return value.
is equivalent to
person.setName("Foo")
5 of 8
11/10/2011 10:55 PM
Eclipse Xtend
http://www.eclipse.org/Xtext/xtend/#download
In Xtend you can just use the map extension method, which is available on every instance of java.lang.Iterable and pass it a closure :
persons.map( p | p.name )
Although closures have a Java compatible type, Xtend provides a nicer notation for function types. The following example defines a closure which would be useful to filter a list of persons by a specific name.
val (Person) => Boolean predicate = [ person | "Hans" == person.name ]
You usually don't have to write the types for functions that often, but would write instead:
val predicate = [ Person person | "Hans" == person.name ]
Such a function can be passed to the extension method Iterable.filter((T) => Boolean):
persons.filter(predicate)
Type guards
Type guards let you switch (or match) for types, which is much nicer and less errorprone than the usual lengthy instanceof-cascades we write in Java. In practice it is almost as useful as pattern matching but without introducing all the additional complexity.
6 of 8
11/10/2011 10:55 PM
Eclipse Xtend
http://www.eclipse.org/Xtext/xtend/#download
In Xtend all string literals can span multiple lines by default. Also you can use single quotes or double quotes, to minimize the needd for escape sequences. If you have some text containing a lot of double quotes better use the single quoted string literal and vice versa:
val msg = 'This is some multi line text with "double quotes" in it'
Template expressions can do more than plain multi-line strings. They allow interpolating expressions and support a FOR-loop and an IF-statement. The most compelling feature is however the automatic whitespace handling!
Extension methods
Xtend got its name from the great support for extending existing types using extension methods. Extension methods allow to add new methods to existing types without touching them. In Xtend local methods are always available as extension methods and are available on the member scope of the first argument's type. Given the following method definition ...
/** * will be available as extension method locally. */ def getFullName(Person p) { p.firstName + " " + p.lastName }
This way you can define layer-specific libraries for your domain model, without poluting the model. And the best thing is, you can easily change the implementation without touching the code. All you need to do is to change the configuration of the dependency injection container. If you wonder how you get polymorphism into this, that's what multiple dispatch is for.
. So it's basically syntactic sugar, but it reads better and the content assist in the IDE can be much more helpful.
Static extensions
Xtend puts a couple of default extension methods on the scope by default. They are mostly higher-order functions for Java's collection library. However, you can use any existing static method as an extension method if you use the keyword extension in the static import:
import static extension java.util.Collections.*
7 of 8
11/10/2011 10:55 PM
Eclipse Xtend
http://www.eclipse.org/Xtext/xtend/#download
The visitor pattern is actually a work-around for the lack of multiple dispatch. By default Xtend (like Java) links overloaded methods at compile time based on the static types of the arguments:
def example() { val Shape s = new Rectangle() println(s.label) // prints "some shape" val Rectangle r = new Rectangle() println(r.label) // prints "a rectangle" } def label(Shape s) { "some shape" } def label(Rectangle r) { "a rectangle" }
def example() { val Shape s = new Rectangle() println(s.label) // prints "a rectangle" !!! val Rectangle r = new Rectangle() println(r.label) // prints "a rectangle" } def dispatch label(Shape s) { "some shape" } def dispatch label(Rectangle r) { "a rectangle" }
Note, that the multiple dispatch behavior is compiled into the declaration, so it will always behave the same no matter whether it's called from Java or Xtend.
8 of 8
11/10/2011 10:55 PM