Groovy Programming Language
-
Upload
aniruddha-chakrabarti -
Category
Software
-
view
366 -
download
0
Transcript of Groovy Programming Language
Aniruddha ChakrabartiAVP and Chief Architect, Digital, Mphasis
[email protected] | linkedin.com/in/aniruddhac | slideshare.net/aniruddha.chakrabarti | Twitter - anchakra
What is Groovy
• Powerful, object oriented, and dynamic language (has features similar to other popular dynamic languages like Python, Ruby and Smalltalk)
• Groovy is optionally typed • Has static-typing and static compilation capabilities, for the Java platform aimed at
improving developer productivity• Targeted for JVM – gets compiled to Java bytecode at runtime. • Integrates smoothly with any Java program and libraries• Very suitable for scripting though not limited to scripting.
A multi-faceted language for the Java platform
JVM
Java Scala Groovy Clojure Jython
CLR (.NET)
VB F# IronPythonC# IronRuby
Popular Language Virtual Machines
A bit of history
• August 2003 - James Strachan first talked about the development of Groovy• b/w 2004 and 2006 - Several versions were released • January 2007 - After the JCP standardization process began, the version
numbering changed and a version called "1.0" was released on. … various betas and release candidates numbered
• December 2007 - Groovy 1.1 Final was released and immediately rebranded as Groovy 1.5 as a reflection of the many changes made.
• November 2008 - SpringSource acquired the Groovy and Grails company (G2One). In August 2009 VMWare acquired SpringSource
• July 2012 - Groovy 2.0 was released. Added static compilation and a static type checker to Groovy.
• April 2013 - Groovy and Grails formed part of Pivotal (JV b/w EMC and VMware) product portfolio.
• April 2015 - Pivotal ceased sponsoring Groovy and Grails from April 2015. Groovy submitted to become a project at The Apache Software Foundation
• Groovy has gained quite a lot of popularity in recent times and have raised to 17th spot from 36th spot in an year
• Most popular alternate to Java on JVM platform
http://www.tiobe.com/tiobe_index
First program
• Groovy programs do not need a main entry point, as required in Java• No need to explicitly specify System.out.println – only println is sufficient
println("Hello Groovy")
• Method calls can omit the parentheses if there is at least one parameter and there is no ambiguity – so the program could be further simplified to
println "Hello Groovy"
Importing Packages
System.out.println("Hello Java" )
println "Hello Groovy"
• Groovy automatically imports these packages • groovy.lang.*• groovy.util.* • java.lang.* • java.util.* • java.net.* • java.io.* • Classes java.math.BigInteger and BigDecimal
Comments
• Single line comment// this would print Hello Groovy to consoleprintln("Hello Groovy")
• Multi line comment/* This isan example ofmultiline comment */println("Hello Groovy")
• Shebang line - understood by UNIX systems which allows scripts to be run directly from the command-line.
#! single line comment in the format of shebang lineprintln "Hello from the shebang line" # must be the first character of the file. Any indentation would yield a compilation error.
Variables and Type Inference
• Declared with explicit type declarationint no = 1bool isTodayHoliday = truefloat salary = 1234.567String message = "Hello World"
• Declared without any type declaration using def (type is inferred)def no = 1 // implicitly typed to Integerdef isTodayHoliday = true // implicitly typed to Booleandef salary = 1234.567 // implicitly typed to BigDecimaldef message = "Hello World“ // implicitly typed to String
Constants
• Declared with explicit type declarationconst PI = 3.14println PI
PI = 3.17 // does not compile and throws a compile time error
Types
• Groovy supports the same primitive types as those defined by the Java Language Specification
• Integral types - byte (8 bit), short (16 bit), int (32 bit) and long (64 bit)• Floating point types - float (32 bit) and double (64 bit)• boolean (true, false)• char - 16 bit, usable as a numeric type, representing an UTF-16 code• Primitive types are represented as wrapper classes (java.lang)
Primitive type Wrapper classboolean Boolean
char Character
short Short
int Integer
long Long
float Float
double Double
def x = 10println x
println x .getClass()// class java.lang.Integer
Dynamic typing
• In contrast to statically typed languages like Java, C#, Groovy is a dynamically typed language (like JavaScript) that supports dynamic typing
def x = 10 // integerprintln x
x = "Hello World" // stringprintln x
x = true // booleanprintln x
x = 123.4567 // doubleprintln x
Strings
• Single quoted string – represents java.lang.String objects, does not support interpolation
• Double quoted string – represents java.lang.String objects or groovy.lang.Gstring (which supports interpolation). If interpolation is not used then java.lang.String is used, otherwise groovy.lang.Gstring is used.
• Triple quoted string – allows multiline strings
def (name, org) = ["RK", "Mphasis"] // same as def name = "RK"; def org = "Mphasis"
println("My name is ${name} and I work for ${org}")println("My name is ${name} and I work for ${org}")println('My name is ${name} and I work for ${org}')
My name is RK and I work for MphasisMy name is RK and I work for MphasisMy name is ${name} and I work for ${org}
String Interpolation
• Any Groovy expression can be interpolated in all string literals, apart from single and triple single quoted strings.
• Interpolation is the act of replacing a placeholder in the string with its value upon evaluation of the string.
• The placeholder expressions are surrounded by ${} or prefixed with $ for dotted expressions.
def name = "Bill"def age = 25println("Name - $name , Age - $age")
println("2 + 3 = ${2 + 3}") // prints 2 + 3 = 5
def person = [name:"Bill",age:25]println("Name - $person.name, Age - ${person.age + 1}")// prints Name - Bill, Age - 26
Array
• Any Groovy expression can be interpolated in all string literals, apart from single and triple single quoted strings.
• Interpolation is the act of replacing a placeholder in the string with its value upon evaluation of the string.
• The placeholder expressions are surrounded by ${} or prefixed with $ for dotted expressions.
String [] cities = ['Kolkata','Bangalore','Amsterdam']println(cities)println(cities.getAt(1)) // prints Bangaloreprintln(cities[1]) // prints Bangaloreprintln(cities instanceof String[]) // prints true
println(cities.length) // prints 3println(cities.size()) // prints 3
if else• Similar to Javadef age = 10
if (age >= 18 && age <= 60) { println "You can vote, you have to stand in a queue"}else if (age > 60) { println "You can vote but no need to stand in a queue"}else { println "You cannot vote" }
• Braces could be removed for single statementif (age >= 18 && age <= 60) println "You can vote, you have to stand in a queue"else if (age > 60) println "You can vote but no need to stand in a queue"else println "You cannot vote"
if else• It’s possible to specify it in a single line –
def age = 20
if (age >= 18 && age <= 60) println "Can vote, come in queue"else if (age > 60) println "Can vote right away"else println "Cannot vote"
Turnery operator (elvis)• Supports Turnery operator similar to Java –
def isFTE = false
def salary = isFTE == true ? 100 : 75println salary // prints 75
• For value assignment checking null elvis operator ?: could be used
def defaultSalary
def salary = defaultSalary ?: 75println salary // prints 75
defaultSalary = 150salary = defaultSalary ?: 75println salary // prints 150
switch
// Employee Type // 1 = FTE, // 2 = Contractor, // 3 = Retired
def employeeType = 2 switch (employeeType) { case 1: println "You are FTE" break case 2: println "You are Contractor" break case 3: println "You are Retired" break}
// Employee Type - FTE, Contractor, // Retired
def employeeType = "Retired" switch (employeeType) { case "FTE": println "You are FTE" break case "Contractor": println "You are Contractor" break case "Retired": println "You are Retired" break}
• Java switch statements could be used for int only (or for byte , char and short that gets converted to int when used for switch), Java 7 allows switching strings
• Groovy switch statements are more flexible than Java
switch (cont’d)• Not only String, Int other types like enum also could be used in switch
enum Employees { FTE, Contractor, Retired}
def emp = Employees.FTE
switch (emp) { case Employees.FTE: println "You are a FTE" break case Employees.Contractor: println "You are a Contractor" break case Employees.Retired: println "You are Retired" break default: println "Can not decide employee type"}
while• Groovy supports the usual while {… } loops like Java• Groovy does not support do while
def ctr = 0
while (ctr < 5) { println ctr ctr++}
for in loop• Similar to Java for each
// primeNos is a list of single digit prime numbers// List are similar to Arrays, but more powerfuldef primeNos = [1,3,5,7]
for (no in primeNos){ println no}
• Braces could be removed for single statementdef cities = ['Bangalore','Kolkata','London','Paris'] for (city in cities) println city
Classical for loop• Similar to Java for
for(int ctr=0;ctr<5;ctr++) { println ctr}
• Braces could be removed for single statementfor(int ctr=0;ctr<5;ctr++) println ctr
Methods (Functions)
• A method is defined with a return type or with the def keyword, to make the return type untyped.
• A method can also receive any number of arguments, which may not have their types explicitly declared.
• Java modifiers can be used (public, private, protected) normally, and if no visibility modifier is provided, the method is public.
// method declarationdef sayHello() { println "Hello"}// method invokationsayHello()
// Removing parenthesis for parameterless methods are not allowedsayHello // this would not compile
// Java way ...void sayHello(){ println "Hello"}
Methods (cont’d)
// method declarationdef sayHello() { println "Hello"}// method invokationsayHello()
// Removing parenthesis for parameterless methods are not allowedsayHello // this would not compile
Methods
// smilimar to Java, Cint add(int num1, int num2) { return num1 + num2}
// similar to dynamic languages def sub(num1, num2) { num1 - num2}
// could be further shortended to def mul(num1, num2) { num1 * num2 }
println(add(20, 10)) // 30println(sub(20, 10)) // 10println(mul(20, 10)) // 200
Methods – Named & Default Arguments
• Default arguments make parameters optional. If the argument is not supplied, the method assumes a default value.
def add(i = 10, j = 20){ i+j}
println(add()) // 30println(add(200, 100)) // 300println(add(100)) // 120
println(add(j=300, i = 200)) // 500println(add(i=300)) // 320
Methods – varargs
• Groovy supports methods with a variable number of arguments.• Denoted by … parameter name
def printMessage(message, ... props){ println message println props println props.length}
printMessage("Hello")printMessage("Hello","Arg1","Arg2")printMessage("Hello",["Arg1","Arg2","Arg3","Arg4"])
Optionality (Low ceremony, Less friction)
• Optional parentheses - Method calls can omit the parentheses if there is at least one parameter and there is no ambiguity
println 'Hello World'println(Math.max(5, 10)) // parentheses are required here• Optional Semicolon - Semicolons at the end of the line can be omitted, if the line
contains only a single statement. String msg = "Hello"; def ctr = 10 • Optional return - the last expression evaluated in the body of a method or a closure
is returned. This means that the return keyword is optional.• Optional public keyword - By default, Groovy classes and methods are public,
compared to private in Java
return statement is optional
• Single line commentdef add(num1, num2){ num1 + num2 // same as return num1 + num2}
println(add(20,10)) // prints 30
Collection Types
• Groovy supports the following collection types• Range• Map• List
Range• Allows creating a sequence of values - influenced by Range type in Python which
behaves almost identical to Groovy Range. Not supported in Java. • These can be used as List since Range extends java.util.List.• Are specified using the double dot .. range operator between the left and the right
bound.def nos = 1 .. 10 // 1 is left bound, 10 is right boundprintln(nos) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
• The ..< range operator specifies a half-exclusive range--that is, the value on the right is not part of the range
def nos = 1 .. <10 // 1 is left bound, 9 is right boundprintln(nos) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
• The range operator along with for in loop could be used for quick traversalfor (x in 1..5) println(x)
Range (cont’d)
• Could be used for other types also, not only numeric typesdef chars = 'a'..'g'println(chars) // [a, b, c, d, e, f, g]
• Supports methods like size(), get(index), contains(value) etc
def nos = 1..10println(nos.size()) // 10println(nos.getAt(2)) // 3println(nos[2]) // 3
println(nos.contains(2)) // trueprintln(nos.contains(12)) // false
List• Lists are similar to Array, but is more flexible. List is an ordered collection of objects.• Each list expression creates an implementation of java.util.List.nos = [1,3,5,7]println(nos) // prints [1,3,5,7]
• List elements could be accessed and updated using indexprintln(0) // prints 1 – index is 0 basedprintln(1) // prints 3println(-1) // prints 3println(-2) // prints 5
nos[0] = 11 // updates first or 0th element to 11println(nos) // prints [11,3,5,7]
nos[1..3] = [13,15,17] // updates first or 0th element to 11println(nos) // prints [11,13,15,17]
List
• Lists can contain elements of different typesnos = [1,3,5,7,'Kolkata','Bangalore']
• Elements could be added using +=nos += [5 0,true,100,"Minneapolis"]println(nos) // [1, 3, 5, 7, Kolkata, Bangalore, 50, true, 100, Minneapolis]
• Elements could be added using -=nos -= ['Kolkata','Minneapolis','Bangalore',true]println(nos) // [1, 3, 5, 7, 50, 100]
• Even * operator works with Listsalph = ['a','c'] println(alph * 2) // [a,c,c,a]println(alph * 3) // [a,c,c,a,a,c]
List
• Lists can contain elements of different typesdef primes = []primes.add(1)primes.add(3)primes.add(5)
println primes[1] // prints 3
println(primes.get(2)) // prints 5println(primes.getAt(2)) // prints 5
primes[2] = 7println primes[2] // prints 7
Map
• Collection that stores the key value pairs• Maps store and retrieve values by key, whereas lists retrieve them by numeric
index.• Called Dictionaries in some other languages.def designations = [ 11 : 'SVP', 10 : 'VP', 9 : 'AVP', 8 : 'Sr. Manager', 7 : 'Manager']
println designations[10] // prints VPdesignations[10] = 'Vice President'println designations[10] // prints Vice President
Map
• Keys can be strings also, need not only be intdef capitals = [ 'IN' : 'New Delhi', 'USA' : 'Washington', 'UK' : 'London']
println capitals['IN'] // prints New Delhicapitals['USA'] = 'Washington DC'println capitals['USA'] // prints Washington DC
println capitals.size() // prints 3
Map
• Has methods to write and read key, value pairs.def statusCodes = [:]
statusCodes.put(200,'OK')statusCodes.put(400,'Bad Request')
println statusCodes.get(200)
Collection methods
• Has methods to write and read key, value pairs.def languages = ['Java','Python','C#','Groovy']
println(languages.reverse()) // [Groovy, C#, Python, Java]println(languages.sort(false)) // [C#, Groovy, Java, Python]
println(languages.contains('Ruby')) // falseprintln(languages.containsAll('Java','Groovy')) // true
Class• Groovy classes are very similar to Java classes, compatible at JVM level. • They may have methods and fields/properties, which can have the same modifiers
(public, protected, private, static, etc) as Java classes.• Groovy classes are bit different from their Java counterparts -
• Public fields are turned into properties automatically, which results in less verbose code, without so many getter and setter methods.
• Their declarations and any property or method without an access modifier are public.• Classes do not need to have the same name of the files where they are defined.• One file may contain one or more classes (if a file contains no classes, it is considered a
script)
class Employee{ def Name = "" def Age = 0}
def emp = new Employee()emp.Name = "Bill"emp.Age = 25println("Name - $emp.Name , Age - $emp.Age")
Class constructor
• With Constructorclass Employee{ def Name; def Age
Employee(name, age){ this.Name = name this.Age = age }}
def emp = new Employee("Bill", 25)println("Name - $emp.Name , Age - $emp.Age")
Class (cont’d)
• With Methodclass Employee{ def Name; def Age
Employee(name, age){ this.Name = name this.Age = age } def increaseAgeBy(byAge){ this.Age += byAge } def displayInfo(){ println("Name - ${this.Name} , Age - ${this.Age}") }}
def emp = new Employee("Bill", 25)emp.increaseAgeBy(5)emp.displayInfo()
Class (cont’d)• Class can have Static methods, properties and fieldsclass Employee{ def Name; def Age def static RetirementAge = 60
Employee(name, age){ }}
println(Employee.RetirementAge)
class Employee{ private static _minJoiningAgeMale = 21 private static _minJoiningAgeFemale = 18 def static getMinJoiningAge(isMale = true) { if (isMale){ return _minJoiningAgeMale } else{ return _minJoiningAgeFemale } } } println(Employee.getMinJoiningAge()) println(Employee.getMinJoiningAge(isMale = false))
Inner Class• Inner classes are defined within another classes. • The enclosing class can use the inner class as usual. On the other side, a inner class can
access members of its enclosing class, even if they are private. • Classes other than the enclosing class are not allowed to access inner classes.
class Employee { def name = ""; boolean isFTE = true def GetSalary(){ def calc = new EmployeeSalaryCalculator() calc.CalculateSalary() } class EmployeeSalaryCalculator{ // EmployeeSalaryCalculator is inner class def CalculateSalary(){ if (isFTE) // can access field/properties of declaring class 100 else 75 } }}
def emp = new Employee()emp.name = "Bill"println(emp.GetSalary())
Inheritance• Similar to Java inheritance, single inheritance tree - Inheritance from multiple parent
classes now allowed.class Human { def Talk(){ println "Human.Talk" }}
class Employee extends Human { def Work(){ println "Employee.Work" }}
def e = new Employee()e.Talk()e.Work()
Inheritance (cont’d)• Single inheritance tree - Inheritance from multiple parent classes now allowed.class Living { def name = "" def walk() { println "Living Walk" }}
class Human{ def think() { println "Human Think" }}
class Employee extends Living, Human{ // Does not compile def work() { println "Employee Work" }}
def emp = new Employee()emp.name = "AC"emp.walk()emp.think()emp.work()
Abstract Class• Abstract classes represent generic concepts, thus, they cannot be instantiated.• Their members include fields/properties and abstract or concrete methods. • Abstract methods do not have implementation, and must be implemented by concrete
subclasses.• Abstract classes can have concrete methods, but should have atleast one abstract method
abstract class Living { def name = "" def walk() println "Living Walk" abstract def think()}
class Human extends Living { def think() println "Human Think"}
def human = new Human()human.name = "AC"human.walk() // Living Walkhuman.think() // Human Think
Interface• Defines a contract that a class needs to conform to - only defines a list of methods
that need to be implemented, but does not define the methods implementation.interface Walkable{ def walk()}
interface Runnable{ def run()}
class Human implements Walkable,Runnable{ def walk(){ println "I can walk" } def run(){ println "I can run" }}
def human = new Human()human.walk() // print “I can walk”human.run() // print “I can run”
enum
enum Employees { FTE, Contractor}
def emp = Employees.FTE
switch (emp) { case Employees.FTE: println "You are a FTE" break case Employees.Contractor: println "You are a Contractor" break}
Exception handling• Same as Java – supports try, catch, finally. Supports multi catch similar to Javadef main(){ def errorType = 1 try { switch(errorType) { case 0: throw new ArithmeticException("Can not divide by zero") break case 1: throw new IOException("IO exception ocurred") break case 2: throw new Exception("Looks like something went wrong") break } } catch(ArithmeticException | IOException ex) { println ex } catch(Exception ex) { println ex } finally { println "finallly block called" }}
main()
GDK – Groovy Development Kit• Similar to JDK, Groovy has a GDK (Groovy Development Kit) that has extra
functionality (additional API) on top of Java JDK.• Example – Additional functionality for string and number type, File handling, I/O,
additional Date & Calendar classes etc.
def str = "Groovy"
println strprintln(str.count("o"))println(str.contains("g"))
println(str.center(20))println(str.multiply(4))println(str.reverse())println(str.minus("vy"))
str = "notepad"str.execute()
Features unique to Groovy
Closure
• In Groovy, Closure is anonymous block of code that can take arguments, return a value and be assigned to a variable
• Closures could be passed as parameter to functions and could be returned from functions
• A closure may reference variables declared in its surrounding scope.• Closure syntax - { [closureParameters -> ] statements }def var_name = { [closureParameters -> ] statements }
Closure
• Without a parameterdef work = { println "Work Called" }work()
• With a parameterdef sayHello = { name -> println("Hello $name") }sayHello("Shreya")
def add = { a,b -> a+b }// this is same as declaring a regular method/function// def add2(a,b) { return a+b }println(add(20,10))
Closure Parameters
• Parameters of closures follow same principle as parameters of regular methods:• an optional type• a name• an optional default value• parameters are separated by comma
def add = { a, b=100 -> a+b } // b has a default value of 100println(add(20))
def sub = { a=20, b=10 -> a-b } // both a & b has default valuesprintln(add(b:120, a:90))
def sub = { a=20, b=10 -> a-b } // both a & b has default valuesprintln(sub(b=120, a=90))
• With a parameter
Currying
• In Groovy, currying refers to the concept of partial application.• Currying in Groovy will let you set the value of one parameter of a closure, and it
will return a new closure accepting one less argument.• It does not correspond to the real concept of currying in functional programming
because of the different scoping rules that Groovy applies on closures.
Left Currying: Sets the left most parameter of a closure
def displayMsg = {noOfTimes, message -> println(message * noOfTimes) }displayMsg(5, "Hello") // prints HelloHelloHelloHelloHello
// First Level of Currying – sets the first most parameter of the // closure noOfTimes to 2def displayMessageTwice = displayMsg.curry(2)displayMessageTwice("Groovy") // prints GroovyGroovy
// Second Level of Curryingdef displayHelloTwice = displayMessageTwice.curry("Hello")displayHelloTwice() // prints HelloHello
Currying
Right Currying: Sets the right most parameter of a closure
def displayMsg = {noOfTimes, message -> println(message * noOfTimes) }displayMsg(5, "Hello") // prints HelloHelloHelloHelloHello
// First Level of Currying – sets the right most parameter of the // closure message to Groovydef displayGroovy = displayMsg.rcurry("Groovy")displayGroovy(3) // prints GroovyGroovyGroovy
// Second Level of Curryingdef displayGroovyFourTimes = displayGroovy.rcurry(4)displayGroovyFourTimes() // prints GroovyGroovyGroovyGroovy
Trait (aka Mixins)
• Single line comment
GrandParent
Parent
Child
Single Inheritance
Parent1
Child
Parent2
Multiple Inheritance usingInheritance hierarchy
GrandParent1 GrandParent2 Vehicle
Car HasAC
Mixin
Base class
Inheritance hierarchy
Trait
• Single line commenttrait Flyable{ def fly(){ println "I can fly" }}
trait Runnable{ def run(){ println "I can run" }}
class Bird implements Flyable, Runnable{}
def bird = new Bird()bird.run() // prints "I can run"bird.fly() // prints "I can fly"
Groovy style guide
• Do not use semicolon for terminating statement / end of line• Not using return statement• Do not use both def and type while declaring variables (def String city = “Blore”) –
use either def or type• For scripting def is more suitable for most cases
• Do not use explicitly public for classes and methods as Groovy makes them public by default
• Use Groovy properties instead of private backing field and java style getter, setter• User string interpolation instead of manually formatting the string• Try to use Groovy Collection classes (range, list, map) before Java collection
classes
http://www.groovy-lang.org/style-guide.html
Resources
• Groovy website - http://www.groovy-lang.org/• Online Groovy Documentation - http://
www.groovy-lang.org/single-page-documentation.html • Online REPL - https://groovyconsole.appspot.com/