60
Ознакомление с груви Евгений Борисов

Groovy jug-moscow-part 1

Embed Size (px)

Citation preview

Ознакомление с грувиЕвгений Борисов

Пробуем на вкус: Замыкания и IO

def number = 0

new File('data.txt').eachLine { line ->

number++

println "$number: $line"

}

Получаем:

1: first line

2: second line

Пробуем на вкус: Коллекции и свойства

def classes = [String, List, File]

for (clazz in classes) {

println clazz.package.name

}

Получаем:

java.lang

java.util

java.io

А можно даже так:

println( [String, List, File]*.package*.name )

Пробуем на вкус: XML, и тот легко

Допустим у нас есть XML:

<?xml version="1.0" ?>

<customers>

<corporate>

<customer name="Bill Gates" company="Microsoft" />

<customer name="Tim Cook" company="Apple" />

<customer name="Larry Ellison" company="Oracle" />

</corporate>

<consumer>

<customer name="John Doe" />

<customer name="Jane Doe" />

</consumer>

</customers>

Пробуем на вкус: XML, и тот легко

def customers = new XmlSlurper().parse(new File('customers.xml'))

for (customer in customers.corporate.customer) {

println "${customer.@name} works for ${customer.@company}"

}

Получаем:Bill Gates works for Microsoft

Steve Jobs works for Apple

Jonathan Schwartz works for Sun

Чтобы создать groovy project

• gradle init --type groovy-library

Немного истории

• James Strachan разработал груви в 2003 году

• Groovy 1.0 – 2007

• Groovy 2.0 – 2012

• Groovy 3.0 – планируется на 2014, на когда-нибудь

• Сегодня – 2.3

Джава и Груви – братья навек

Groovy

• Java-подобный синтакс (можно писать на груви, как будто это джава)

• Взял лучшее от Python, Ruby, Smalltalk, Java Script и C#

• Компилируется в джава классы

• Может использоваться в любом Java проекте

• Может использоваться как скриптовой язык

Можно смешивать не только водку с пивом

Груви лаконичный

• today = new Date() // Groovy

• import java.util.*;

• Date today = new Date(); // Java

• require 'date'

• today = Date.new # Ruby

• import java.util._

• var today = new Date // Scala

Default Groovy imports

• import java.io.*

• import java.lang.*

• import java.math.BigDecimal

• import java.math.BigInteger

• import java.net.*

• import java.util.*

• import groovy.lang.*

• import groovy.util.*

Сравнение с синтексом джавы

• ; - не обязательно

• return не обязательно.

• не обязательно в декларации указывать тип переменной, ставьте def, если не известно что за тип (только без фанатизма)

•В статических методах this будет указывать на класс

•package friendly делается через аннотацию

•() при вызова метода опциональны, если метод принимает хотябы один параметр и нет параметров одного типа

Отличия от джавы

•Внутренние классы не поддерживаются – а зачем?

•Нет checked exceptions – а зачем?

•Груви может обращаться к private методам и филдам у любых

классов как груви так джавы

•Это баг, на него открыта джира

•Они делают вид, что это фича, и поэтому не чинят

Hello world на Groovy

print / println в groovy

• Можно написать: println(‘bla bla bla’)

• Можно написать: println ‘bla bla bla’

• Такой же overloading для примитивных типов, как в джаве

Определение параметров

• int x = 42

• x = 42

• def x = 42

• Множественное присвоение поддерживается

• def (x,y,z) = [42, new Dog(), 'куку']

Вместо пар можно…

А потом этим можно пользоваться вот так…

Output:

Groovy casting – duck typing

• def nameAndAge() {

• [name: 'john', age:30]

• }

• Person p = nameAndAge() as Person

Если я хожу, как утка, плаваю как утка, крякаю, как

утка, то наверное я утка !!!

Strings

•Стринги в груви могут определять как через двойные, так и

через одинарные кавычки

•А еще можно создавать стринг в несколько строчек

используя тройные двойные кавычки

•Можно и тройные одинарные кавычки, но это не GStrings

String str = """Вообще не

реальная

ситуация"""

String str = /он сказал:

“писать 2 \\ лучше чем 4\\”/

GString

• Пишутся в двойных кавычках

• Могут содержать выражения

• println "цитата: $str"

• println "diff between x and y = ${x-y}"

• println "Ленин снял кепку и

сказал:${new Ленин().вещатьСБронивика()}"

Вкусняшки от грувей

Не уверен – не обгоняй

Не уверен, что не null делай вот так

Groovy truth

Groovy Truth

•В джаве if принимает только boolean.

•А вот Groovy:

Задание

• Что будет если написать…

Person person = new Person(age: 200)

if(person) println 'YES‘

• Сделайте так, чтобы ‘yes’ печаталось, только когда персон младше 120 лет

• Пошла подсказка- > переопределите asBoolean

Elvis Operator ?:

Операторы

• Груви даёт возможность переопределять функциональность операторов

• При помощи переопределения соответствующих методов

• Начнём с ==

• Угадайте, какой метод надо переопределить?

• Правильно - equals

isperson.is(person2)

Если == делегирует в equals, то как же мне

сравнивать референсы??

Задание

• Напишите класс Person у которого есть имя и возраст

• Создайте 2 персона и сравните их при помощи ==

• Теперь пропишите метод equals для персона и сравните еще раз

Задолбались писать equals и hashcode?

@EqualsAndHashCode

Вкусняшки от грувей

• @ToString

• @EqualsAndHashcode

• @Canonical

• @Immutable

Еще операторы

•a +b = a.plus(b)

•a – b = a.minus(b)

•a * b = a.multiply(b)

•a** b = a.power(b)

•a / b = a.div(b)

•a % b = a.mod(b)

Еще задание

• Есть класс Employee (age, salary)

• Есть класс Bonus(amount, age)

• employee + bonus должен работать следующим образом.

• Если возраст работника выше возраста указанного в объекте бонус, значит его зарплата увеличивается на amount

•a | b = a.or(b)

•a & b = a.and(b)

•a ^ b = a.xor(b)

•a++ or ++a = a.next()

•a-- or --a = a.previous()

•a[b] = a.getAt(b)

•a[b]=c тоже самое a.putAt(b,c)

•a << b = a.leftShift(b)

•a >> b = a.rightShift(b)

Именно поэтому << никто не использует по прямому назначению его почти все переопределяют

Листы

• def someList = [1,2,3,4]

• def emptyList = []

• someList[0]

• someList[5] = 6

• someList << ‘java’ // Добить элемент в конец листа

• someList << java << groovy // добавить 2 элемента в конец листа

• someList += otherList

• List diff = listA - listB

Листы

• someList[1..3] // вытащить sublist

• someList[2..4] = [ 12, 13, 14 ] // переопределить sublist

• someList[1,3,5..7,9] // вытащить sublist

Диапазоны (ranges)

• def x = 1..10

• assert x.contains(5) // не имплементировано для doubles, floats и BigDecimal

• assert x.contains(15) == false

• assert x.size() == 10

• assert x.from == 1

• assert x.to == 10

• assert x.min==1

• assert x.max==10

• assert x.reverse() == 10..1

Циклы

• Вы конечно можете использовать и старый синтекс джавы.

Как вы напечатаете имя файла без расширерения, если расширение 3 буквы?• String str = “minsk.gif”;

• str = str[0..-5] println “str = $str”

• print str

Switch

• В отличие от джавы, где Switch это антипаттерн, в груви он очень даже распространен.

• Его можно применять на: primitives, enums, strings, regex и любой другой объект, класс которого имплементирует метод isCase()

isCase пропиcан для

--> a.equals(b)

--> a.isInstance(b)

--> a.contains(b)

--> a.contains(b)

--> a.matcher(b.toString()).matches()

--> (a==null && b==null) || a.equals(b)

--> a.call(b)

• Объект

• Класс

• Коллекшон

• Диапазон

• Паттерны

• Стринги

• Клоужеры

Еще Switch

Maps

• По умолчанию ключ это String

• Но если (a) это переменная, а мы хотим уточнить что а это буква, то тогда…

Задание

• Создайте лист Персонов и внесите туда несколько объектов

• Добавьте каждому персону 10 лет к возрасту

• Распечатайте весь лист

• Сколько строчек кода вы написали?

• А должно быть 3

Клоужеры• def sayHello = { println "Hello!" }• sayHello.call() или sayHello()

• def sayHelloTo = { person -> println "Hello $person !" }• sayHelloTo("John")

• void printFunctionResultOnName (String name, Closure func) {• println func(name)• }• // напечатает"gradla"• printFunctionResultOnName("gredla") { String name ->• name.replace (“e", “a")• }

Closures and collections

Как вы сделаете comparator на джаве?

• Надо отсортировать лист персонов в первую очередь по имени, но если они совпадают то по возрасту

• Пишите, Шура пишите… сколько у вас строчек кода?

• А у меня одна:

• persons.sort({a,b-> a.name.compareTo(b.name) ?: a.age.compareTo(b.age)})

А сколько строчек кода надо чтобы…

• У вас есть лист Животных (собаки, кошки….)

• У каждого животного есть метод makeVoice, который возвразаетстринг

• А нужен лист звуков всех животных вашего зооппарка

• Пишите шура, Пишите!

Вкусняшки от грувей для работы с листами

• clone – клонирует лист.

• collect – проходится по всем объектам листа и возвращает новый лист.

List ages = persons.collect {"Person's age: $it.age"}

•*. – Так же как collect. def ages = persons*.getAge()

• find – Возвращает первый элемент который соответствует критерию

•persons.find({it.age>3})

• findAll – returns a list. persons.findAll({it.age>3})

•every – вернет правду если все элементы соблюдают усовия

•boolean b = persons.every({it.age>11})

Напишите Equalator

• Метода должен получать лист персонов, персона и equalator

• А возвращать сколько раз этот персон находится в листе.

• Как сравнивать персонов будет говорить equalator

Переопределение метода для объекта

Добавление нового метода / property к объекту

Можно добавить метод классу на лету

• Person.metaClass.printName = {print delegate.name}

• delegate – обращение к объекту

• Все объекты созданные до того, как метод был добавлен, не будут его иметь