Sunday, May 6, 2012

Xtend - Basics by Example



Extending my Basics by Example series to a new language. today's version of the post written in Xtend.

You can copy and paste the code below in your favorite IDE/Editor and start playing and learning with it. This little "working" program will teach you the basics of the Programming Language.

There are some "comments" on the code added just to tell you what are or how are some features called. In case you want to review the theory, you can read my previous post, where I give a definition of each of the concepts mentioned on the code. You can find it here: http://carlosqt.blogspot.com/2010/08/new-series-languages-basics-by-example.html 


Greetings Program - Verbose
// Xtend Basics
package com.series
import java.util.Calendar
import java.util.GregorianCalendar

public class Greet {
    // Fields or Attributes
    private String message  
    private String name
    private int loopMessage 
    // Getters and Setters. 
    // M7 will introduce annotation @Property to auto generate them (if not present)
    def public String getMessage() {  
        return this.message
    }  
    def public void setMessage(String value) {  
        this.message = this.capitalize(value)  
    }  
    def public String getName() {  
        return this.name
    }  
    def public void setName(String value) {  
        this.name = this.capitalize(value)  
    }  
    def public int getLoopMessage() {  
        return this.loopMessage  
    }  
    def public void setLoopMessage(int value) {  
        this.loopMessage = value  
    }  
    // Constructor  
    public new() {
        this.message = ""  
        this.name = ""
        this.loopMessage = 0           
    }
    // Overloaded Constructor  
    public new(String message, String name, int loopMessage) {  
        this.message = this.capitalize(message)  
        this.name = this.capitalize(name)  
        this.loopMessage = loopMessage  
    }    
    // Method 1  
    def private String capitalize(String value) {  
        // "if-then-else" statement  
        if (value.length() >= 1) {  
            return value.toFirstUpper()  
        }  
        else  {  
            return ""  
        }  
    }  
    // Method 2  
    def public void Salute() {  
        // "for (each)" statement
        for (int i : 0..this.loopMessage) {  
            println(this.message + " " + this.name + "!")  
        }  
    }  
    // Overloaded Method 2.1  
    def public void Salute(String message, String name, int loopMessage) {  
        // "while" statement  
        var int i = 0  
        while(i < loopMessage) {  
            println(this.capitalize(message) + " " + this.capitalize(name) + "!")
            i = i + 1
        }  
    }      
    // Overloaded Method 2.2  
    def public void Salute(String name) {  
        // "switch/case" statement  
        // doesn't work with iterables (i.e: case 6..11: ...)
        // doesn't allow multiple expressions in one case (i.e: case i>=6 && i<=11: ...)
        // doesn't allow fall through (i.e: case 6: case 7: case N: ...)
        // so better to use if-else-if expression instead
        var GregorianCalendar dtNow = new GregorianCalendar()        
        val int hh = dtNow.get(Calendar::HOUR_OF_DAY) 
        if (hh >= 6 && hh <= 11) this.message = "good morning,"        
        else if (hh >= 12 && hh <= 17) this.message = "good afternoon,"
        else if (hh >= 18 && hh <= 22) this.message = "good evening,"            
        else if (hh == 23 || (hh >= 0 && hh <= 5)) this.message = "good night,"
        else this.message = "huh?"        
        println(this.capitalize(this.message) + " " + this.capitalize(name) + "!")  
    }  
}
package com.series
import java.util.Scanner  
import java.lang.System 
// Greet Program
public class Program { 
    def public static void main(String[] args) {
        // Define variable object of type Greet and Instantiate. Call Constructor  
        val Greet g = new Greet()           
        // Call Setters  
        g.setMessage("hello")  
        g.setName("world")  
        g.setLoopMessage(5)  
        // Call Method 2  
        g.Salute()
        // Overloaded Method 2.1 and Getters  
        g.Salute(g.getMessage(), "xtend", g.getLoopMessage())  
        // Overloaded Method 2.2  
        g.Salute("carlos")
        
        // Stop and exit  
        println("Press any key to exit...")        
        val Scanner in = new Scanner(System::in)  
        val String line = in.nextLine()  
        in.close()                 
    }    
}

Greetings Program - Minimal
// Xtend Basics
import java.util.Calendar
import java.util.GregorianCalendar

class Greet {
    // Fields or Attributes
    private String message  
    private String name
    private int loopMessage    
    // Getters and Setters. 
    // M7 will introduce annotation @Property to auto generate them (if not present)    
    def getMessage() {  
        message
    }  
    def setMessage(String value) {  
        message = capitalize(value)  
    }  
    def getName() {  
        name
    }  
    def setName(String value) {  
        name = capitalize(value)  
    }  
    def getLoopMessage() {  
        loopMessage  
    }  
    def setLoopMessage(int value) {  
        loopMessage = value  
    }  
    // Constructor  
    new() {
        message = ""  
        name = ""
        loopMessage = 0           
    }
    // Overloaded Constructor  
    new(String message, String name, int loopMessage) {  
        this.message = capitalize(message)  
        this.name = capitalize(name)  
        this.loopMessage = loopMessage  
    }    
    // Method 1  
    def private String capitalize(String value) {  
        // "if-then-else" statement  
        if (value.length >= 1)  
            value.toFirstUpper  
        else    
            ""  
    }  
    // Method 2  
    def Salute() {  
        // "for (each)" statement
        for (i : 0..loopMessage) {  
            println(message + " " + name + "!")  
        }  
    }  
    // Overloaded Method 2.1  
    def Salute(String message, String name, int loopMessage) {  
        // "while" statement  
        var i = 0  
        while(i < loopMessage) {  
            println(capitalize(message) + " " + capitalize(name) + "!")
            i = i + 1
        }  
    }      
    // Overloaded Method 2.2  
    def Salute(String name) {  
        // "switch/case" statement  
        // doesn't work with iterables (i.e: case 6..11: ...)
        // doesn't allow multiple expressions in one case (i.e: case i>=6 && i<=11: ...)
        // doesn't allow fall through (i.e: case 6: case 7: case N: ...)
        // so better to use if-else-if expression instead
        var dtNow = new GregorianCalendar        
        val hh = dtNow.get(Calendar::HOUR_OF_DAY) 
        if (hh >= 6 && hh <= 11) message = "good morning,"        
        else if (hh >= 12 && hh <= 17) message = "good afternoon,"
        else if (hh >= 18 && hh <= 22) message = "good evening,"            
        else if (hh == 23 || (hh >= 0 && hh <= 5)) message = "good night,"
        else message = "huh?"        
        println(capitalize(message) + " " + capitalize(name) + "!")  
    }  
}
import java.util.Scanner  
// Greet Program
class Program { 
    def static main(String[] args) {
        // Define variable object of type Greet and Instantiate. Call Constructor  
        val g = new Greet           
        // Call Setters  
        g.setMessage("hello")  
        g.setName("world")  
        g.setLoopMessage(5)  
        // Call Method 2  
        g.Salute
        // Overloaded Method 2.1 and Getters  
        g.Salute(g.getMessage, "xtend", g.getLoopMessage)  
        // Overloaded Method 2.2  
        g.Salute("carlos")
        
        // Stop and exit  
        println("Press any key to exit...")        
        val in = new Scanner(System::in)  
        val line = in.nextLine  
        in.close
    }    
}


And the Output is:




Auto-Implemented Properties in Xtend

Auto-implemented properties enable you to quickly specify a property of a class without having to write code to Get and Set the field. In Xtend you will use the @Property annotation which will generate a Java-Bean-style getter and setter (if the field is not final) for an annotated field and only generated when not explicitly defined.


// Xtend Basics  
class AutoImplementedProperties {  
    // Fields + Auto-Implemented Properties  
    @Property String message  
    @Property String name  
    @Property int loopMessage  
    // Methods  
    def salute() {    
        println('''«message.toFirstUpper» «name.toFirstUpper» «loopMessage»!''')
    }  
}
class Program { 
    def static void main(String[] args) {
        var g = new AutoImplementedProperties => [ 
            // Call Set Property  
            message = "hello"         
            name = "world"
            loopMessage = 5        
        ]
        // print them out  
        g.salute
        // and print them again using Get Properties  
        println('''«g.message» «g.name» «g.loopMessage»!''')
    }    
}

And the output is:


2 comments:

  1. Hi Carlos,

    M7 is out. Although your code would compile the following is a it more idiomatic:

    // Xtend Basics
    class AutoImplementedProperties {
    // Fields + Auto-Implemented Properties
    @Property String message
    @Property String name
    @Property int loopMessage
    // Methods
    def salute() {
    print('''«message.toFirstUpper» «name.toFirstUpper» «loopMessage»!''')
    }
    }

    class Program {
    def static main(String[] args) {
    var g = new AutoImplementedProperties => [
    message = "hello"
    name = "world"
    loopMessage = 5
    ]
    // print them out
    g.salute
    // and print them again using Getters or Get Properties
    println(g.message + " " + g.name + " " + g.loopMessage + "!")
    }
    }

    ReplyDelete
    Replies
    1. Hi Sven,

      Code is now updated to M7.
      Auto implemented properties worked like a charm. I didn't know xtend supported String Interpolation also :) and good idea to use the new With operator.

      Great work guys!

      Delete