blob: 1701f31700a35b47e8526e6c06b5ca079581c59e [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Xtend - Classes and Members</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description"
content="Xtend is a statically typed programming language sitting on top of Java.">
<meta name="author" content="Sven Efftinge">
<meta name="author" content="Miro Spoenemann">
<!-- styles -->
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<!-- Le fav and touch icons -->
<link rel="shortcut icon" href="/xtend/images/favicon.png">
<link href="/xtend/css/bootstrap.css" rel="stylesheet" type='text/css'>
<link href="/xtend/css/bootstrap-responsive.css" rel="stylesheet" type='text/css'>
<link href="/xtend/css/shield-responsive.css" rel="stylesheet" type='text/css'>
<link href='/xtend/css/fonts.css' rel='stylesheet' type='text/css'>
<link href="/xtend/css/prettyPhoto.css" rel="stylesheet" media="screen" type='text/css'>
<link href="/xtend/css/prettify.css" type="text/css" rel="stylesheet"/>
<link href="/xtend/css/style.css" rel="stylesheet" type='text/css'>
<!--[if lt IE 9]>
<link href="css/iebugs.css" rel="stylesheet" type='text/css'>
<![endif]-->
<!-- BEGIN Cookie Consent
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.0.3/cookieconsent.min.css" />
<script src="//cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.0.3/cookieconsent.min.js"></script>
<script>
window.addEventListener("load", function(){
window.cookieconsent.initialise({
"palette": {
"popup": {
"background": "#000"
},
"button": {
"background": "#f1d600"
}
},
"theme": "edgeless",
"type": "opt-in",
onInitialise: function (status) {
var type = this.options.type;
var didConsent = this.hasConsented();
if (type == 'opt-in' && didConsent) {
// TODO: enable cookies
}
if (type == 'opt-out' && !didConsent) {
// TODO: disable cookies
}
},
onStatusChange: function(status, chosenBefore) {
var type = this.options.type;
var didConsent = this.hasConsented();
if (type == 'opt-in' && didConsent) {
// TODO: enable cookies
}
if (type == 'opt-out' && !didConsent) {
// TODO: disable cookies
}
},
onRevokeChoice: function() {
var type = this.options.type;
if (type == 'opt-in') {
// TODO: disable cookies
}
if (type == 'opt-out') {
// TODO: enable cookies
}
},
"content": {
"href": "http://www.eclipse.org/legal/privacy.php"
}
})});
</script>
END Cookie Consent -->
</head>
<body>
<!-- Navbar -->
<div class="navbar navbar-fixed-top"
style="border-bottom: 1px solid #000;">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse"
data-target=".nav-collapse"> <span class="icon-bar"></span> <span
class="icon-bar"></span> <span class="icon-bar"></span>
</a> <a class="brand" href="/xtend/index.html"></a>
<div class="nav-collapse collapse" style="height: 0px;">
<ul class="nav">
<li ><a href="/xtend/download.html">Download</a></li>
<li ><a href="/xtend/documentation/index.html">Documentation</a></li>
<li ><a href="/xtend/community.html">Community</a></li>
<li ><a href="http://xtext.org">Xtext</a></li>
<li ><a href="http://www.eclipse.org">Eclipse.org</a></li>
</ul>
<!--div class="btn-group pull-right">
<div class="g-plusone" data-href="http://www.xtend-lang.org"></div>
</div-->
</div>
<!--/.nav-collapse -->
</div>
</div>
</div>
<!-- Navbar End -->
<div class="page-content">
<script>
function startSearch(event) {
if (event.keyCode == 13) {
var q = 'site:eclipse.org/xtend/documentation+' + event.target.value;
window.open('https://www.google.com/search?q=' + q, "_self");
}
}
</script>
<div class="wrapper">
<div id="page">
<div class="inner">
<div id="maincontainer" class="container">
<span class="edit-on-github pull-right">
<a href="https://github.com/eclipse/xtext/edit/website-published/xtend-website/documentation/202_xtend_classes_members.md">Edit on Github</a>
</span>
<div class="span3" style="margin-left: 0px;">
<div class="search-bar">
<img src="/xtend/images/search-gray.png"/>
<input type="search" id="google-search" onkeyup="startSearch(event);"/>
</div>
<ul id="nav-outline">
<li>&nbsp;</li>
<li style="color : #333;">Getting Started</li>
<li><a href="101_gettingstarted.html">Hello World</a></li>
<li><a href="102_moviesexample.html">The Movies Example</a></li>
<li>&nbsp;</li>
<li style="color : #333;">Reference Documentation</li>
<li><a href="201_types.html">Java Interoperability</a></li>
<li><a href="202_xtend_classes_members.html">Classes and Members</a></li>
<li><a href="203_xtend_expressions.html">Expressions</a></li>
<li><a href="204_activeannotations.html">Active Annotations</a></li>
</ul>
</div>
<div class="span9 doc-contents">
<h1 id="xtend-classes-members">Classes and Members</h1>
<p>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 class definitions. The classes in fact are directly translated to Java classes in the corresponding Java package. A class can have constructors, fields, methods and annotations.</p>
<p>Here is an examplary Xtend file:</p>
<pre><code class="language-xtend">package com.acme
import java.util.List
class MyClass {
String name
new(String name) {
this.name = name
}
def String first(List&lt;String&gt; elements) {
elements.get(0)
}
}
</code></pre>
<h2 id="package-decl">Package Declaration</h2>
<p>Package declarations can look like those in Java. Two small, optional differences:</p>
<ul>
<li>An identifier can be escaped with a <code>^</code> character in case it conflicts with a keyword.</li>
<li>The terminating semicolon is optional.</li>
</ul>
<pre><code class="language-xtend"> package com.acme
</code></pre>
<h2 id="imports">Imports</h2>
<p>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 <code>^</code>. In contrast to Java, the terminating semicolon is optional. Non-static wildcard type imports are deprecated for the benefit of better usability and well defined dependencies.</p>
<p>Xtend also features static imports for importing static fields and methods. The semantics and syntax are just like in Java.</p>
<p>As in Java all classes from the <code>java.lang</code> package are implicitly imported.</p>
<pre><code class="language-xtend">import java.math.BigDecimal
import static java.util.Collections.sort
import static org.junit.Assert.*
</code></pre>
<p>Static methods can also be imported as <code>extension</code>s. See the section on <a href="202_xtend_classes_members.html#extension-methods">extension methods</a> for details.</p>
<h2 id="xtend-class-declaration">Class Declaration</h2>
<p>The class declaration reuses a lot of Java’s syntax but still is a bit different in some aspects: All Xtend types are <code>public</code> by default since that’s the common case. Java’s “package private” default visibility is declared by the more explicit keyword <code>package</code> in Xtend. In contrast to Java, Xtend supports multiple public top level class declarations per file. Each Xtend class is compiled to a separate top-level Java class.</p>
<p>Abstract classes are defined using the <code>abstract</code> modifier as in Java. See also <a href="202_xtend_classes_members.html#abstract-methods">abstract methods</a>.</p>
<p>Xtend’s approach to inheritance is conceptually the same as in Java. Single inheritance of classes as well as implementing multiple interfaces is supported. Xtend classes can extend other Xtend classes, and even Java classes can inherit from Xtend classes. If no super type is specified, <a href="http://docs.oracle.com/javase/8/docs/api/java/lang/Object.html">Object</a> is used.</p>
<p>The most simple class looks like this:</p>
<pre><code class="language-xtend">class MyClass {
}
</code></pre>
<p>A more advanced generic class declaration in Xtend:</p>
<pre><code class="language-xtend">class ArrayList&lt;E&gt; extends AbstractList&lt;E&gt;
implements List&lt;E&gt;, RandomAccess,
Cloneable, java.io.Serializable {
...
}
</code></pre>
<h2 id="constructors">Constructors</h2>
<p>An Xtend class can define any number of constructors. Unlike Java you do not have to repeat the name of the class over and over again, but use the keyword <code>new</code> to declare a constructor. Constructors can also delegate to other constructors using <code>this(args...)</code> in their first line.</p>
<pre><code class="language-xtend">class MyClass extends AnotherClass {
new(String s) {
super(s)
}
new() {
this("default")
}
}
</code></pre>
<p>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 <code>super(args...)</code> as the first expression in the body of the constructor.</p>
<p>The default visibility of constructors is <code>public</code> but you can also specify an explicit visiblity <code>public</code>, <code>protected</code>, <code>package</code> or <code>private</code>.</p>
<h2 id="fields">Fields</h2>
<p>A field can have an initializer. Final fields are declared using <code>val</code>, while <code>var</code> introduces a non-final field and can be omitted. Yet, if an initializer expression is present, the type of a field can be inferred if <code>val</code> or <code>var</code> was used to introduce the field. The keyword <code>final</code> is synonym to <code>val</code>. Fields marked as <code>static</code> will be compiled to static Java fields.</p>
<pre><code class="language-xtend">class MyClass {
int count = 1
static boolean debug = false
var name = 'Foo' // type String is inferred
val UNIVERSAL_ANSWER = 42 // final field with inferred type int
...
}
</code></pre>
<p>The default visibility for fields is <code>private</code>. You can also declare it explicitly as being <code>public</code>, <code>protected</code>, <code>package</code> or <code>private</code>.</p>
<p>A specialty of Xtend are fields that provide <em>extension methods</em> which are covered in <a href="202_xtend_classes_members.html#extension-methods">their own section</a>.</p>
<h2 id="methods">Methods</h2>
<p>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 <a href="202_xtend_classes_members.html#polymorphic-dispatch">later</a>.</p>
<pre><code class="language-xtend">def String first(List&lt;String&gt; elements) {
elements.get(0)
}
</code></pre>
<p>Method declarations start with the keyword <code>def</code>. The default visibility of a method is <code>public</code>. You can explicitly declare it as being <code>public</code>, <code>protected</code>, <code>package</code> or <code>private</code>.</p>
<p>Xtend supports the <code>static</code> modifier for methods and can <a href="202_xtend_classes_members.html#inferred-return-types">infer</a> the return type if it is not explicitly given:</p>
<pre><code class="language-xtend">def static createInstance() {
new MyClass('foo')
}
</code></pre>
<p>As in Java, vararg parameters are allowed and accessible as array values in the method body:</p>
<pre><code class="language-xtend">def printAll(String... strings) {
strings.forEach[ s | println(s) ]
}
</code></pre>
<p>It is possible to infer the return type of a method from its body. Recursive methods and abstract methods have to declare an explicit return type.</p>
<h3 id="abstract-methods">Abstract Methods</h3>
<p>An abstract method in Xtend does not define a body and must be declared within an <code>abstract</code> class or an interface. Also specifying the return type is mandatory since it cannot be inferred.</p>
<pre><code class="language-xtend">abstract class MyAbstractClass() {
def String abstractMethod() // no body
}
</code></pre>
<h3 id="overriding-methods">Overriding Methods</h3>
<p>Methods can override other methods from the super class or implement interface methods using the keyword <code>override</code>. If a method overrides a method from a super type, the <code>override</code> keyword is mandatory and replaces the keyword <code>def</code>. The override semantics are the same as in Java, e.g. it is impossible to override <code>final</code> methods or invisible methods. Overriding methods inherit their return type from the super declaration.</p>
<p>Example:</p>
<pre><code class="language-xtend">override String second(List&lt;String&gt; elements) {
elements.get(1)
}
</code></pre>
<h3 id="declared-exceptions">Declared Exceptions</h3>
<p>Xtend does not force you to catch or declare checked exceptions. Nevertheless, you can still declare the exceptions thrown in a method’s body using the <code>throws</code> clause as in Java.</p>
<p>If you do not declare checked exceptions in your method but they are possibly thrown in your code, the compiler will throw the checked exception silently (using the sneaky-throw technique introduced by <a href="http://projectlombok.org/features/SneakyThrows.html">Lombok</a>).</p>
<pre><code class="language-xtend">/*
* throws an Exception
*/
def void throwException() throws Exception {
throw new Exception
}
/*
* throws an Exception without declaring it
*/
def void sneakyThrowException() {
throw new Exception
}
</code></pre>
<p>Optional validation of checked exception is supported, too, and can be configured on the respective Eclipse preference page for the Xtend Errors and Warnings.</p>
<h3 id="inferred-return-types">Inferred Return Types</h3>
<p>If the return type of a method can be inferred from its body it does not have to be declared.</p>
<p>That is the method</p>
<pre><code class="language-xtend">def String second(List&lt;String&gt; elements) {
elements.get(1)
}
</code></pre>
<p>could be declared like this:</p>
<pre><code class="language-xtend">def second(List&lt;String&gt; elements) {
elements.get(1)
}
</code></pre>
<p>The return type is mandatory for abstract method declarations as well as for recursive implementations.</p>
<h3 id="generic-methods">Generic Methods</h3>
<p>You can specify type parameters on methods. A parameterized variant of the method from the previous section, could look like this:</p>
<pre><code class="language-xtend">def &lt;T&gt; second(List&lt;T&gt; elements) {
elements.get(1)
}
</code></pre>
<p>Type parameter bounds and constraints are supported and share the same syntax and semantics as defined in the <a href="http://docs.oracle.com/javase/specs/jls/se6/html/classes.html#8.4.4">the Java Language Specification</a>.</p>
<h3 id="operator-declaration">Operator Declarations</h3>
<p>Xtend supports operator overloading based on an operator-name-mapping as explained in the <a href="203_xtend_expressions.html#operators">section on operators</a>. To declare an operator one can either declare a simple method using the operator’s name or by using the operator directly like in the following:</p>
<pre><code class="language-xtend">class Money {
def + (Money other) { ... }
def - (Money other) { ... }
def * (BigDecimal times) { ... }
...
}
</code></pre>
<h3 id="polymorphic-dispatch">Dispatch Methods</h3>
<p>Generally, method resolution and binding is done statically at compile time as 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 <a href="202_xtend_classes_members.html#extension-methods">extension methods</a> you would like to have polymorphic behavior.</p>
<p>A dispatch method is declared using the keyword <code>dispatch</code>.</p>
<pre><code class="language-xtend">def dispatch printType(Number x) {
"it's a number"
}
def dispatch printType(Integer x) {
"it's an int"
}
</code></pre>
<p>For a set of visible dispatch methods in the current type hierarchy with the same name and the same number of arguments, the compiler infers a synthetic dispatcher method. This dispatcher uses the common super type of all declared arguments. The method name of the actual dispatch cases is prepended with an underscore and the visibility of these methods is reduced to protected if they have been defined as public methods. Client code always binds to the synthesized dispatcher method.</p>
<p>For the two dispatch methods in the example above the following Java code would be generated:</p>
<pre><code class="language-java">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 if (x != null) {
return _printType(x);
} else {
throw new IllegalArgumentException("Unhandled parameter types: " +
Arrays.&lt;Object&gt;asList(x).toString());
}
}
</code></pre>
<p>Note that the <code>instanceof</code> cascade is ordered such that more specific types are handled first.</p>
<p>The default visibility of the dispatch cases is <code>protected</code>. If all dispatch methods explicitly declare the same visibility, this will be the visibility of the inferred dispatcher, too. Otherwise it is <code>public</code>. The comparison of the parameter types is performed from left to right. That is in the following example, the second method declaration is considered more specific since its first parameter type is the most specific:</p>
<pre><code class="language-xtend">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"
}
</code></pre>
<p>generates the following Java code :</p>
<pre><code class="language-java">public String printTypes(final Number x, final Number y) {
if (x instanceof Integer
&amp;&amp; y != null) {
return _printTypes((Integer)x, y);
} else if (x != null
&amp;&amp; y instanceof Integer) {
return _printTypes(x, (Integer)y);
} else {
throw new IllegalArgumentException("Unhandled parameter types: " +
Arrays.&lt;Object&gt;asList(x, y).toString());
}
}
</code></pre>
<p>The code is compiled in a way that a <code>null</code> reference is never a match. <code>null</code> values can be handled by dispatch cases that use the parameter type <a href="http://docs.oracle.com/javase/8/docs/api/java/lang/Void.html">Void</a>.</p>
<pre><code class="language-xtend">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"
}
</code></pre>
<p>This compiles to the following Java code:</p>
<pre><code class="language-java">public String printType(final Number x) {
if (x instanceof Integer) {
return _printType((Integer)x);
} else if (x != null) {
return _printType(x);
} else if (x == null) {
return _printType((Void)null);
} else {
throw new IllegalArgumentException("Unhandled parameter types: " +
Arrays.&lt;Object&gt;asList(x).toString());
}
}
</code></pre>
<h4 id="dispatch-methods-and-inheritance">Dispatch Methods and Inheritance</h4>
<p>All visible Java methods from all super types that are conformant to the compiled representation of a dispatch method are also included in the dispatcher. Conforming means they have the expected number of arguments and have the same compiled name with the prepended underscore.</p>
<p>For example, consider the following Java class :</p>
<pre><code class="language-java">public abstract class AbstractLabelProvider {
protected String _label(Object o) {
// some generic implementation
}
}
</code></pre>
<p>and the following Xtend class which extends the Java class :</p>
<pre><code class="language-xtend">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
}
}
</code></pre>
<p>The resulting dispatch method in the generated Java class <code>MyLabelProvider</code> would then look like this:</p>
<pre><code class="language-java">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 if (it != null) {
return super._label(it);
} else {
throw new IllegalArgumentException("Unhandled parameter types: " +
Arrays.&lt;Object&gt;asList(it).toString());
}
}
</code></pre>
<h4 id="static-dispatch-methods">Static Dispatch Methods</h4>
<p>Also static dispatch methods are supported. A mixture of static and non-static dispatch methods is prohibited.</p>
<h3 id="create-methods">Create Methods</h3>
<p>Create methods in Xtend allow to do graph transformation in one pass where it usually needs two passes. That means you don’t need to separate a translation from one graph to another in the typical two phases: tree construction and interlinking the tree nodes. You basically just need to write the whole transformation using create methods and the built-in identity preservation will take care of the rest.</p>
<p>Consider you want to create a copy of the following list of persons into a :</p>
<pre><code>Fred Flintstone {
marriedTo Willma Flintstone
friendWith Barny Rubble
}
Willma Flintstone {
marriedTo Fred Flintstone
}
Barny Rubble {
friendWith Fred Flintstone
}
</code></pre>
<p>A function like the following could do the trick :</p>
<pre><code class="language-xtend">def List&lt;Person&gt; copyPersons(List&lt;Person&gt; persons) {
persons.map[copy]
}
def copy(Person p) {
val result = new Person()
result.name = p.name
// The following is wrong and results in a stack overflow
result.friendWith = p.friendWith.map[copy]
result.marriedWith = p.marriedWith.map[copy]
}
</code></pre>
<p>The problem with that code is that we don’t track the origins of the created copies. This is the main problem with model transformations. The classic solution is to run the copying in two passes. First we create all instances and then we establish the links. Although it works it results in cluttered and non coherent code. Xtend’s create functions handle this problem by introducing identity perservation by tracking the origin of each created instance. Therefore, a create function takes two expressions. One to instantiate the actual object and a second one to initialize it.</p>
<pre><code class="language-xtend">def create result: new Person copy(Person p) {
result.name = p.name
// now it works
result.friendWith = p.friendWith.map[copy]
result.marriedWith = p.marriedWith.map[copy]
}
</code></pre>
<p>If you do not specify the name of the result variable it is assumed to be the implicit receiver variable <code>it</code>, which can be skipped in feature calls inside the body. Furthermore, you can define the return type of a create function:</p>
<pre><code class="language-xtend">def Person create new PersonImpl() copy(Person p) {
/* it.*/name = p.name
friendWith = p.friendWith.map[copy]
marriedWith = p.marriedWith.map[copy]
}
</code></pre>
<h4 id="how-it-works">How it works</h4>
<p>In addition to the keyword <code>create</code> one specifies two expressions. The first expression is the factory to create an instance while the second will initialize it further. Prior to invoking the factory expression, a cache lookup is performed to find a previously created instance for the very same arguments. If there is no such instance, the factory expression is evaluated and the result is stored in the cache. Subsequently the main expression (also called the initializer expression) is evaluated. This happens only if there was no previously created instance available in the cache. If that expression in turn calls the create function transitively using the same set of arguments the previously instantiated and cached object is returned. Note that the object is probably currently initialized. That is, its internal state may not yet be available. The lifecycle of the cache is attached to the instance of the declaring Xtend class. That is you can control how long the cache lives by means of Guice.</p>
<hr />
<h2 id="annotations">Annotations</h2>
<p>Annotations are available on classes, fields, methods and parameters. They are prefixed with the <code>@</code> character and accept a number of key-value pairs or a default value for the annotation property named <code>value</code>. Annotation values that expect arrays can handle single values, too. Value arrays are enclosed in array literals <code>#['first', 'second']</code>. The semantics for annotations are exactly like defined in the <a href="http://docs.oracle.com/javase/specs/jls/se6/html/interfaces.html#9.7">Java Language Specification</a>. Here is an example:</p>
<pre><code class="language-xtend">@TypeAnnotation("some value")
class MyClass {
@FieldAnnotation(value = @NestedAnnotation(true))
static val CONSTANT = 'a compile-time constant'
@MethodAnnotation(constant = CONSTANT)
def String myMethod(@ParameterAnnotation String param) {
//...
}
}
</code></pre>
<p>In addition <a href="204_activeannotations.html">Active Annotations</a> allow users to participate in compilation of Xtend code to Java source code.</p>
<h2 id="extension-methods">Extension Methods</h2>
<p>Extension methods allow to add new methods to existing types without modifying them. 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 method invocation, the method can be called with the first argument as its receiver - it can be called as if the method was one of the argument type’s members.</p>
<pre><code class="language-xtend">"hello".toFirstUpper() // calls StringExtensions.toFirstUpper("hello")
</code></pre>
<p>Method calls in extension syntax often result in more readable code, as they are chained rather than nested. Another benefit of extensions is that you can add methods which are specific to a certain context or layer of your application.</p>
<p>For instance, you might not want to put UI-specific methods and dependencies into your domain model classes. Therefore this functionality is often defined in static methods or methods in utility classes or service layers. That works, but the code is less readable and less object-oriented if you call methods like this. In Java you often see code like this:</p>
<pre><code class="language-java">persistenceManager.save(myObject);
</code></pre>
<p>Without tying your entities to the persistenceManager, extension methods allow you to write</p>
<pre><code class="language-xtend">myObject.save
</code></pre>
<p>There are different ways to make methods available as extensions, which are described in the following sections.</p>
<h3 id="library-extensions">Extensions from the Library</h3>
<p>The Xtend library puts a lot of very useful extension methods on existing types from the Java SDK without any further ado.</p>
<pre><code class="language-xtend">"hello".toFirstUpper // calls StringExtensions.toFirstUpper(String)
listOfStrings.map[ toUpperCase ] // calls ListExtensions.&lt;T, R&gt;map(List&lt;T&gt; list, Function&lt;? super T, ? extends R&gt; mapFunction)
</code></pre>
<p>Have a look at the JavaDoc to learn about the available functionality:</p>
<ul>
<li><a href="https://github.com/eclipse/xtext-lib/blob/master/org.eclipse.xtext.xbase.lib/src/org/eclipse/xtext/xbase/lib/ObjectExtensions.java">ObjectExtensions</a></li>
<li><a href="https://github.com/eclipse/xtext-lib/blob/master/org.eclipse.xtext.xbase.lib/src/org/eclipse/xtext/xbase/lib/IterableExtensions.java">IterableExtensions</a></li>
<li><a href="https://github.com/eclipse/xtext-lib/blob/master/org.eclipse.xtext.xbase.lib/src/org/eclipse/xtext/xbase/lib/MapExtensions.java">MapExtensions</a></li>
<li><a href="https://github.com/eclipse/xtext-lib/blob/master/org.eclipse.xtext.xbase.lib/src/org/eclipse/xtext/xbase/lib/ListExtensions.java">ListExtensions</a></li>
<li><a href="https://github.com/eclipse/xtext-lib/blob/master/org.eclipse.xtext.xbase.lib/src/org/eclipse/xtext/xbase/lib/CollectionExtensions.java">CollectionExtensions</a></li>
<li><a href="https://github.com/eclipse/xtext-lib/blob/master/org.eclipse.xtext.xbase.lib/src/org/eclipse/xtext/xbase/lib/BooleanExtensions.java">BooleanExtensions</a></li>
<li><a href="https://github.com/eclipse/xtext-lib/blob/master/org.eclipse.xtext.xbase.lib/src/org/eclipse/xtext/xbase/lib/IntegerExtensions.java">IntegerExtensions</a></li>
<li><a href="https://github.com/eclipse/xtext-lib/blob/master/org.eclipse.xtext.xbase.lib/src/org/eclipse/xtext/xbase/lib/FunctionExtensions.java">FunctionExtensions</a></li>
</ul>
<h3 id="local-extension-methods">Local Extension Methods</h3>
<p>All visible non-static methods of the current class and its super types are automatically available as extensions. For example</p>
<pre><code class="language-xtend">class MyClass {
def doSomething(Object obj) {
// do something with obj
}
def extensionCall(Object obj) {
obj.doSomething() // calls this.doSomething(obj)
}
}
</code></pre>
<p>Local static methods have to be made available through an import like any other static method.</p>
<h3 id="extension-imports">Extension Imports</h3>
<p>In Java, you would usually write a helper class with static methods to decorate an existing class with additional behavior. In order to integrate such static helper classes, Xtend allows to put the keyword <code>extension</code> after the <code>static</code> keyword of a <a href="202_xtend_classes_members.html#imports">static import</a> thus making all imported static functions available as extensions methods.</p>
<p>The following import declaration</p>
<pre><code class="language-xtend">import static extension java.util.Collections.singletonList
</code></pre>
<p>allows us to use singletonList methods like this:</p>
<pre><code class="language-xtend">new MyClass().singletonList()
// calls Collections.singletonList(new MyClass())
</code></pre>
<h3 id="extension-provider">Extension Provider</h3>
<p>By adding the <code>extension</code> keyword to a field, a local variable or a parameter declaration, its instance methods become extension methods.</p>
<p>Imagine you want to have some layer specific functionality on a class <code>Person</code>. Let us say you are in a servlet-like class and want to persist a <code>Person</code> using some persistence mechanism. Let us assume <code>Person</code> implements a common interface <code>Entity</code>. You could have the following interface</p>
<pre><code class="language-java">interface EntityPersistence {
public save(Entity e);
public update(Entity e);
public delete(Entity e);
}
</code></pre>
<p>And if you have obtained an instance of that type (through a factory or dependency injection or what ever) like this:</p>
<pre><code class="language-xtend">class MyServlet {
extension EntityPersistence ep = Factory.get(EntityPersistence)
...
}
</code></pre>
<p>You are able to save, update and delete any entity like this:</p>
<pre><code class="language-xtend">val Person person = ...
person.save // calls ep.save(person)
person.name = 'Horst'
person.update // calls ep.update(person)
person.delete // calls ep.delete(person)
</code></pre>
<p>Using the <code>extension</code> modifier on values has a significant advantage over static <a href="202_xtend_classes_members.html#extension-imports">extension imports</a>: Your code is not bound to the actual implementation of the extension method. You can simply exchange the component that provides the referenced extension with another implementation from outside, by providing a different instance.</p>
<h2 id="interfaces">Interface Declarations</h2>
<p>An interface declaration is very similar to the one in Java. An interface can declare fields, which are by default final static therefore must have an initial value. And of course methods can be declared, which are public by default. Interfaces can extend any number of other interfaces and can declare type parameters. Here’s an example:</p>
<pre><code class="language-xtend">interface MyInterface&lt;T&gt; extends OtherInterface {
val CONSTANT = 42
def T doStuff(String ... varArg) throws SomeException
}
</code></pre>
<p>Since version 8 of the Java language, interfaces are allowed to contain non-abstract instance methods, called <a href="http://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html">default methods</a>, as well as static methods. This is also supported in Xtend (since 2.8): if Java 8 is selected as target language version, interfaces are allowed to declare methods with bodies like in the following example.</p>
<pre><code class="language-xtend">interface MyInterface {
def doStuff() {
'This is an instance method returning a string.'
}
static def doGlobalStuff() {
'This is a static method returning a string.'
}
}
</code></pre>
<p>The behavior of non-abstract instance methods is equivalent to that of Java default methods. Since interfaces can extend multiple other interfaces, multiple-inheritance conflicts can occur when different implementations of a method are inherited:</p>
<pre><code class="language-xtend">interface A {
def execute() {
return 1
}
}
interface B {
def execute() {
return 2
}
}
interface C extends A, B {
}
class D implements A, B {
}
</code></pre>
<p>The interface <code>C</code> and the class <code>D</code> are both marked with an error due to the multiple inheritance of the method <code>execute()</code>. There are four ways to resolve the problem.</p>
<ul>
<li>
<p>Redeclare the method as abstract (not allowed for non-abstract classes):</p>
<pre><code class="language-xtend">override execute()
</code></pre>
</li>
<li>
<p>Override the implementation:</p>
<pre><code class="language-xtend">override execute() {
return 3
}
</code></pre>
</li>
<li>
<p>Refer to a supertype implementation:</p>
<pre><code class="language-xtend">override execute() {
A.super.execute()
}
</code></pre>
</li>
<li>
<p>Avoid the inheritance of multiple method implementations in the first place. This is the recommended approach.</p>
</li>
</ul>
<h2 id="annotation-type-declaration">Annotation Type Declarations</h2>
<p>Annotation types can also be declared. The are introduced by the keyword <code>annotation</code> and declare their values with a concise syntax:</p>
<pre><code class="language-xtend">annotation MyAnnotation {
String[] value
boolean isTricky = false
int[] lotteryNumbers = #[ 42, 137 ]
}
</code></pre>
<h2 id="enum-type-declaration">Enum Type Declarations</h2>
<p>Enumeration types are declared like this:</p>
<pre><code class="language-xtend">enum MyColor {
GREEN,
BLUE,
RED
}
</code></pre>
<h2 id="nested-type-declarations">Nested Type Declarations</h2>
<p>Classes, enum, annotation and interface declarations can be nested. Just as in Java nested enums, annotations and interfaces are always static. In Xtend nested classes are also always static. Nested types are public by default and can only be nested within a class, an interface or an annotation declaration.</p>
<pre><code class="language-xtend">class MyClass {
static class NestedClass {}
annotation NestedAnnotation {}
enum NestedEnum {}
interface NestedInterface {}
}
interface MyInterface {
static class NestedClass {}
annotation NestedAnnotation {}
enum NestedEnum {}
interface NestedInterface {}
}
annotation MyAnnotation {
static class NestedClass {}
annotation NestedAnnotation {}
enum NestedEnum {}
interface NestedInterface {}
}
</code></pre>
<hr />
<p><strong><a href="203_xtend_expressions.html">Next Chapter: Expressions</a></strong></p>
</div>
</div>
</div>
</div>
</div>
</div>
<footer class="site-footer">
<div id="extra">
<div class="container inner-footer">
<div class="row">
<div class="span6">
<h3 class="footer-links-header">Quick Links</h3>
<ul class="footer-links clearfix">
<li><a href="http://www.eclipse.org/legal/privacy.php">Privacy Policy</a></li>
<li><a href="http://www.eclipse.org/legal/termsofuse.php">Terms of Use</a></li>
<li><a href="http://www.eclipse.org/legal/copyright.php">Copyright Agent</a></li>
<li><a href="http://www.eclipse.org/legal/">Legal</a></li>
</ul>
<ul class="footer-links clearfix">
<li><a href="http://www.eclipse.org">Eclipse Home</a></li>
<li><a href="http://marketplace.eclipse.org/">Market Place</a></li>
<li><a href="http://live.eclipse.org/">Eclipse Live</a></li>
<li><a href="http://www.planeteclipse.org/">Eclipse Planet</a></li>
</ul>
</div>
<div class="span6">
<!-- Social Media Links -->
<h3 class="footer-links-header"">Social Media</h3>
<ul class="footer-links clearfix">
<li>
<a href="https://twitter.com/xtendlang"><img src="/xtend/images/Twitter-bird-darkgray.png" class="img-responsive" style="margin-right: 5px;height: 1em;" alt="Twitter icon">@xtendlang on Twitter</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<a href="#" class="scrollup fadeOutRight animated" style="display: none;">ScrollUp</a>
<a href="http://dryicons.com/">Icons by http://dryicons.com</a>
<!-- Le javascript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="/xtend/js/jquery-1.7.1.min.js" type="text/javascript"></script>
<script src="/xtend/js/bootstrap.min.js" type="text/javascript"></script>
<!-- include pretty-print files -->
<script src="/xtend/js/prettify.js" type="text/javascript" ></script>
<script src="/xtend/js/lang-xtend.js" type="text/javascript"></script>
<!-- Include the plug-in -->
<script src="/xtend/js/jquery.prettyPhoto.js" type="text/javascript"></script>
<script src="/xtend/js/jquery.easing.1.3.js" type="text/javascript"></script>
<script src="/xtend/js/custom.js" type="text/javascript"></script>
<!--script src="https://apis.google.com/js/platform.js" async defer></script-->
<!--script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push([ '_setAccount', 'UA-2429174-4' ]);
_gaq.push([ '_trackPageview' ]);
(function() {
var ga = document.createElement('script');
ga.type = 'text/javascript';
ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl'
: 'http://www')
+ '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script-->
</footer>
</body>
</html>