Groovy Programming Language

1,832 views 63 slides Mar 10, 2016
Slide 1
Slide 1 of 63
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27
Slide 28
28
Slide 29
29
Slide 30
30
Slide 31
31
Slide 32
32
Slide 33
33
Slide 34
34
Slide 35
35
Slide 36
36
Slide 37
37
Slide 38
38
Slide 39
39
Slide 40
40
Slide 41
41
Slide 42
42
Slide 43
43
Slide 44
44
Slide 45
45
Slide 46
46
Slide 47
47
Slide 48
48
Slide 49
49
Slide 50
50
Slide 51
51
Slide 52
52
Slide 53
53
Slide 54
54
Slide 55
55
Slide 56
56
Slide 57
57
Slide 58
58
Slide 59
59
Slide 60
60
Slide 61
61
Slide 62
62
Slide 63
63

About This Presentation

Tour of Groovy Programming Language. Covers unique Groovy features like dynamic typing, currying, traits, closures etc.


Slide Content

Aniruddha Chakrabarti AVP 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# IronPython C# 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 17 th spot from 36 th 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 console println ("Hello Groovy") ​​​​​​​​​​ Multi line comment /* This is an example of multiline 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 line println "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 declaration int no = 1 bool isTodayHoliday = true float salary = 1234.567 String message = "Hello World" Declared without any type declaration using def (type is inferred) def no = 1 // implicitly typed to Integer def isTodayHoliday = true // implicitly typed to Boolean def salary = 1234.567 // implicitly typed to BigDecimal def message = "Hello World“ // implicitly typed to String

Constants Declared with explicit type declaration const PI = 3.14 println 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 class boolean Boolean char Character short Short int Integer long Long float Float double Double def  x = 10 println  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 // integer println x x = "Hello World" // string println x x = true // boolean println x x = 123.4567 // double println 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 Mphasis My name is RK and I work for Mphasis My 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 = 25 println ("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 Bangalore println (cities[1 ]) // prints Bangalore println (cities instanceof String[]) ​ // prints true println ( cities.length ) // prints 3 println ( cities.size ()) // prints 3

if else Similar to Java def   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 statement 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" ​​​​​​​​​​​​​

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 : 75 println salary ​ // prints 75 For value assignment checking null elvis operator ?: could be used def defaultSalary def salary = defaultSalary ?: 75 println salary​ // prints 75 defaultSalary = 150 salary = defaultSalary ?: 75 println 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 = 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 powerful def primeNos = [1,3,5,7 ] for (no in primeNos ){ println no } Braces could be removed for single statement def 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 statement for( 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 declaration def   sayHello () {      println  "Hello" } // method invokation sayHello () // Removing parenthesis for parameterless methods are not allowed sayHello // this would not compile // Java way ... void sayHello (){ println "Hello" }

Methods (cont’d) // method declaration def   sayHello () {      println  "Hello" } // method invokation sayHello () // Removing parenthesis for parameterless methods are not allowed sayHello // this would not compile

Methods // smilimar to Java, C int 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)) // 30 println(sub(20 , 10)) // 10 println(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 ()) // 30 println(add(200, 100 )) // 300 println(add(100 )) // 120 println (add(j=300, i = 200 )) // 500 println (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 comment def 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 bound println ( 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 bound println ( nos )​ // [1, 2, 3, 4, 5, 6, 7, 8, 9] The range operator along with for in loop could be used for quick traversal for (x in 1..5) println (x)​

Range (cont’d) Could be used for other types also, not only numeric types def chars = ' a '..'g ' println (chars ) // [a, b, c, d, e, f, g ] Supports methods like size(), get(index), contains(value) etc def nos = 1..10 println ( nos.size ()) // 10 println ( nos.getAt (2 )) // 3 println ( nos [2 ]) // 3 println ( nos.contains (2 )) // true println ( 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 index println (0) // prints 1 – index is 0 based println (1) // prints 3 println (-1 ) // prints 3 println (-2) // prints 5 nos [0] = 11 // updates first or 0 th element to 11 println ( nos ) ​​ // prints [11,3,5,7] nos [1..3] = [13,15,17] // updates first or 0 th element to 11 println ( nos )​​ // prints [ 11,13,15,17]

List Lists can contain elements of different types nos  = [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 Lists alph  = [' 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 types def primes = [] primes.add (1) primes.add (3) primes.add (5) println primes[1] // prints 3 println ( primes.get (2)) // prints 5 println ( primes.getAt (2 )) // prints 5 primes[2] = 7 println 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 VP designations[10]​ = 'Vice President' println designations[10] ​ // prints Vice President

Map Keys can be strings also, need not only be int def capitals = [ 'IN' : 'New Delhi', 'USA' : 'Washington', 'UK' : 'London' ] println capitals['IN '] // prints New Delhi capitals['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')) ​ // false println ( 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 = 25 println("Name - $emp.Name , Age - $emp.Age ")

Class constructor With Constructor class 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 Method class 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 fields class  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 Walk human.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 Java def 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 str println ( 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 parameter def work = { println "Work Called" } work() With a parameter def 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 100 println (add(20 )) def   sub  = {  a=20, b=10  ->  a-b  } // both a & b has default values println (add(b:120, a:90)) def sub = { a=20 , b=10 -> a-b } // both a & b has default values println (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 2 def displayMessageTwice = displayMsg . curry (2 ) displayMessageTwice ("Groovy ") // prints GroovyGroovy // Second Level of Currying def 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 Groovy def displayGroovy = displayMsg. rcurry ("Groovy") displayGroovy (3) // prints GroovyGroovyGroovy // Second Level of Currying def displayGroovyFourTimes = displayGroovy. rcurry (4) displayGroovyFourTimes () // prints GroovyGroovyGroovyGroovy

Trait (aka Mixins ) Single line comment GrandParent Parent Child Single Inheritance Parent1 Child Parent2 Multiple Inheritance using Inheritance hierarchy GrandParent1 GrandParent2 Vehicle Car HasAC Mixin Base class Inheritance hierarchy

Trait Single line comment trait 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 /