Groovy presentation

Preview:

DESCRIPTION

Groovy programing language presentation.For more details see my blog.infinitylx.org.ua

Citation preview

Обзор Groovy

Владислав Мережко

План презентации

●JVM, JRE●Groovy syntax●closures (замыкания)●@notation●aliases●metaprogramming●DSL●GPath●Groovy builder●Integration into enfinity

Все точки над «і»

Groovy — объектно-ориентированный язык программирования разработанный для платформы Java как альтернатива языку Java с возможностями Python, Ruby и Smalltalk.

Groovy завершил процесс стандартизации в Java Community Process JSR 241.

Groovy — объектно-ориентированный язык программирования разработанный для платформы Java как альтернатива языку Java с возможностями Python, Ruby и Smalltalk.

Groovy завершил процесс стандартизации в Java Community Process JSR 241.

Java Virtual Machine

● Вы можете использовать любой код написанный на Java

● Получаете все преимущества языка Java:● стабильность JVM● масштабирование● многопоточность● нулевой порог вхождения для Java программистов● и многое другое

● Вы можете использовать любой код написанный на Java

● Получаете все преимущества языка Java:● стабильность JVM● масштабирование● многопоточность● нулевой порог вхождения для Java программистов● и многое другое

DSL

● Язык полностью поддерживает концепцию Domain Specific Language (DSL)

● С помощью Metaprogramming и динамической природы можно легко реализовать свой собственный язык

● Язык полностью поддерживает концепцию Domain Specific Language (DSL)

● С помощью Metaprogramming и динамической природы можно легко реализовать свой собственный язык

Пример

buy 500, "AAPL", 179.30

buy(250, "AAPL", 179.30) //

buy 500, "SUNW", 10.14

sell 350, "AAPL", 179.30

show_transactions "AAPL"

print_portfolio_value

buy 500, "AAPL", 179.30

buy(250, "AAPL", 179.30) //

buy 500, "SUNW", 10.14

sell 350, "AAPL", 179.30

show_transactions "AAPL"

print_portfolio_value

Пример

portfolio = [:] //Holds all of the stock transactions

/**

*A simple object to hold the data for each individual transaction

*/

class StockTransaction {

def tickerSymbol

def numberOfShares

def sharePrice

def type

def transactionDate

}

portfolio = [:] //Holds all of the stock transactions

/**

*A simple object to hold the data for each individual transaction

*/

class StockTransaction {

def tickerSymbol

def numberOfShares

def sharePrice

def type

def transactionDate

}

Пример

def buy(numberOfShares, symbol, sharePrice){

transaction('Buy', numberOfShares, symbol, sharePrice)

}

def sell(numberOfShares, symbol, sharePrice){

transaction('Sell', numberOfShares, symbol, sharePrice)

}

def buy(numberOfShares, symbol, sharePrice){

transaction('Buy', numberOfShares, symbol, sharePrice)

}

def sell(numberOfShares, symbol, sharePrice){

transaction('Sell', numberOfShares, symbol, sharePrice)

}

Пример

def transaction(transactionType, numberOfShares, symbol, sharePrice){

def transaction = new StockTransaction(tickerSymbol:symbol,

numberOfShares:numberOfShares, sharePrice:sharePrice,

type:transactionType, transactionDate:new Date())

println "${transaction.type}ing ${transaction.numberOfShares} shares" +

" of ${transaction.tickerSymbol} at ${transaction.sharePrice}"

if(portfolio[transaction.tickerSymbol] == null){

if(transactionType == 'Buy')

portfolio[transaction.tickerSymbol] = [transaction]

else

println "You can't sell a stock you don't own."

} else{

portfolio[transaction.tickerSymbol] << transaction

}

}

def transaction(transactionType, numberOfShares, symbol, sharePrice){

def transaction = new StockTransaction(tickerSymbol:symbol,

numberOfShares:numberOfShares, sharePrice:sharePrice,

type:transactionType, transactionDate:new Date())

println "${transaction.type}ing ${transaction.numberOfShares} shares" +

" of ${transaction.tickerSymbol} at ${transaction.sharePrice}"

if(portfolio[transaction.tickerSymbol] == null){

if(transactionType == 'Buy')

portfolio[transaction.tickerSymbol] = [transaction]

else

println "You can't sell a stock you don't own."

} else{

portfolio[transaction.tickerSymbol] << transaction

}

}

Результат выполнения

Buying 500 shares of AAPL at 179.30

Buying 250 shares of AAPL at 179.30

Buying 500 shares of SUNW at 10.14

Selling 350 shares of AAPL at 179.30

Sun Aug 17 19:15:05 EDT 2008: Buy 500 shares of AAPL at 179.30

Sun Aug 17 19:15:05 EDT 2008: Buy 250 shares of AAPL at 179.30

Sun Aug 17 19:15:05 EDT 2008: Sell 350 shares of AAPL at 179.30

Your Total Portfolio Value is: 76790.00

Buying 500 shares of AAPL at 179.30

Buying 250 shares of AAPL at 179.30

Buying 500 shares of SUNW at 10.14

Selling 350 shares of AAPL at 179.30

Sun Aug 17 19:15:05 EDT 2008: Buy 500 shares of AAPL at 179.30

Sun Aug 17 19:15:05 EDT 2008: Buy 250 shares of AAPL at 179.30

Sun Aug 17 19:15:05 EDT 2008: Sell 350 shares of AAPL at 179.30

Your Total Portfolio Value is: 76790.00

Замыкание

● Одна из важных особенностей Groovy● Очень много встроенных функций Groovy

принимать замыкания как параметр● Замыкания анонимны● Замыкания имеют доступ к внешним

переменным● Замыкания могуть принимать много переменных

● Одна из важных особенностей Groovy● Очень много встроенных функций Groovy

принимать замыкания как параметр● Замыкания анонимны● Замыкания имеют доступ к внешним

переменным● Замыкания могуть принимать много переменных

Замыкания

● Замыкание имеет вид

{ [аргументиЗамикания->] кодЗамикания }● Все замыкания унаследованы от “Closure”● Чтобы вызвать замыкание можно

воспользоваться один из двух способов

1: closureVar.call();

2: closureVar();

● Замыкание имеет вид

{ [аргументиЗамикания->] кодЗамикания }● Все замыкания унаследованы от “Closure”● Чтобы вызвать замыкание можно

воспользоваться один из двух способов

1: closureVar.call();

2: closureVar();

Пример

square = { it * it }

square(9)● 81

[ 1, 2, 3, 4 ].collect(square)● [1, 4, 9, 16 ]

def printSum = { a, b -> print a+b }

printSum( 5, 7 )● 12

square = { it * it }

square(9)● 81

[ 1, 2, 3, 4 ].collect(square)● [1, 4, 9, 16 ]

def printSum = { a, b -> print a+b }

printSum( 5, 7 )● 12

Пример

def myConst = 5

def incByConst = { num-> num + myConst}

println incByConst(10)● 15

def clos = { print it }

clos( "hi there" ) ● hi there

def myConst = 5

def incByConst = { num-> num + myConst}

println incByConst(10)● 15

def clos = { print it }

clos( "hi there" ) ● hi there

@ннотации

● Аннотации в Groovy позволяют реализовать множественное наследование (@mixin)

● Делегировать вызови методов к свойству класса (@delegate)

● Расширять любые классы, даже final (@category)

● Создавать сиглтоны (@singleton)● Создавать неизменяемые объекты (@immutable)● Создавать ленивые свойства классов (@lazy)

● Аннотации в Groovy позволяют реализовать множественное наследование (@mixin)

● Делегировать вызови методов к свойству класса (@delegate)

● Расширять любые классы, даже final (@category)

● Создавать сиглтоны (@singleton)● Создавать неизменяемые объекты (@immutable)● Создавать ленивые свойства классов (@lazy)

Пример

@Singleton class T {}

● Аналог на Java

public class T {

public static final T instance = new T();

private T() {}

}

@Singleton class T {}

● Аналог на Java

public class T {

public static final T instance = new T();

private T() {}

}

Пример

@Immutable final class Coordinates {

Double latitude, longitude

}

def c1 = new Coordinates(latitude: 48.824068, longitude: 2.531733)

def c2 = new Coordinates(48.824068, 2.531733)

● assert c1 == c2

@Immutable final class Coordinates {

Double latitude, longitude

}

def c1 = new Coordinates(latitude: 48.824068, longitude: 2.531733)

def c2 = new Coordinates(48.824068, 2.531733)

● assert c1 == c2

Пример

class Person {

@Lazy pets = ['Cat', 'Dog', 'Bird']

}

def p = new Person()

assert !(p.dump().contains('Cat'))

assert p.pets.size() == 3

assert p.dump().contains('Cat')

class Person {

@Lazy pets = ['Cat', 'Dog', 'Bird']

}

def p = new Person()

assert !(p.dump().contains('Cat'))

assert p.pets.size() == 3

assert p.dump().contains('Cat')

Пример

import java.text.SimpleDateFormat

class Event {

@Delegate Date when

String title, url

}

def df = new SimpleDateFormat("yyyy/MM/dd")

import java.text.SimpleDateFormat

class Event {

@Delegate Date when

String title, url

}

def df = new SimpleDateFormat("yyyy/MM/dd")

Пример

def gr8conf = new Event(title: "GR8 Conference",

url: "http://www.gr8conf.org",

when: df.parse("2009/05/18"))

def javaOne = new Event(title: "JavaOne",

url: "http://java.sun.com/javaone/",

when: df.parse("2009/06/02"))

assert gr8conf.before(javaOne.when)

def gr8conf = new Event(title: "GR8 Conference",

url: "http://www.gr8conf.org",

when: df.parse("2009/05/18"))

def javaOne = new Event(title: "JavaOne",

url: "http://java.sun.com/javaone/",

when: df.parse("2009/06/02"))

assert gr8conf.before(javaOne.when)

Пример

@Category(Vehicle) class FlyingAbility {

def fly() { "I'm the ${name} and I fly!" }

}

@Category(Vehicle) class DivingAbility {

def dive() { "I'm the ${name} and I dive!" }

}

interface Vehicle {

String getName()

}

@Category(Vehicle) class FlyingAbility {

def fly() { "I'm the ${name} and I fly!" }

}

@Category(Vehicle) class DivingAbility {

def dive() { "I'm the ${name} and I dive!" }

}

interface Vehicle {

String getName()

}

Пример

@Mixin([DivingAbility, FlyingAbility])

class JamesBondVehicle implements Vehicle {

String getName() { "James Bond's vehicle" }

}

assert new JamesBondVehicle().fly() ==

"I'm the James Bond's vehicle and I fly!"

assert new JamesBondVehicle().dive() ==

"I'm the James Bond's vehicle and I dive!"

@Mixin([DivingAbility, FlyingAbility])

class JamesBondVehicle implements Vehicle {

String getName() { "James Bond's vehicle" }

}

assert new JamesBondVehicle().fly() ==

"I'm the James Bond's vehicle and I fly!"

assert new JamesBondVehicle().dive() ==

"I'm the James Bond's vehicle and I dive!"

Metaprogramming

● Возможность языка динамически манипулировать другими программами, включая себя

● Динамически добавлять методы

● AST (Abstract Syntax Tree) преобразование

● Возможность языка динамически манипулировать другими программами, включая себя

● Динамически добавлять методы

● AST (Abstract Syntax Tree) преобразование

Metaprogramming

AST бывает двух видов● Глобальное – применяется во время компиляции

ко всем исходным текстам во время компиляции● Локальное — применяются к отдельным

элементам обозначенным специальными аннотациями

AST бывает двух видов● Глобальное – применяется во время компиляции

ко всем исходным текстам во время компиляции● Локальное — применяются к отдельным

элементам обозначенным специальными аннотациями

Пример

import java.text.NumberFormat

BigDecimal.metaClass.inEuros = {

def EXCHANGE_RATE = 0.53 // (6/16/2011)

NumberFormat nf = NumberFormat.getCurrencyInstance(Locale.US)

nf.setCurrency(Currency.getInstance("EUR"))

nf.format(delegate * EXCHANGE_RATE)

}

● println 2500.00.inEuros()

import java.text.NumberFormat

BigDecimal.metaClass.inEuros = {

def EXCHANGE_RATE = 0.53 // (6/16/2011)

NumberFormat nf = NumberFormat.getCurrencyInstance(Locale.US)

nf.setCurrency(Currency.getInstance("EUR"))

nf.format(delegate * EXCHANGE_RATE)

}

● println 2500.00.inEuros()

Пример

println "Introduction".padRight(15, ".")

println "Introduction".reverse()

//output● Introduction...● noitcudortnI

println "Introduction".padRight(15, ".")

println "Introduction".reverse()

//output● Introduction...● noitcudortnI

Пример

String.metaClass.shout = {->

return delegate.toUpperCase()

}

String.metaClass.toUpperCase = {->

return delegate.toLowerCase()

}

println "Hello MetaProgramming".shout()

//output

hello metaprogramming

String.metaClass.shout = {->

return delegate.toUpperCase()

}

String.metaClass.toUpperCase = {->

return delegate.toLowerCase()

}

println "Hello MetaProgramming".shout()

//output

hello metaprogramming

Aliases and Duck typing

Тут все просто

● def p = System.out.&println;

● p{"Hello"}

● Duck - typing – возможность утверждать что объект имеет определенный тип не на основе наличия в сигнатуре интерфейса, который он имплементирует, а по наличию реализованных методов (оператор AS).

● По сути и это есть более правильный термин для описания типизации в Groovy, чем просто «динамическая типизация»

Тут все просто

● def p = System.out.&println;

● p{"Hello"}

● Duck - typing – возможность утверждать что объект имеет определенный тип не на основе наличия в сигнатуре интерфейса, который он имплементирует, а по наличию реализованных методов (оператор AS).

● По сути и это есть более правильный термин для описания типизации в Groovy, чем просто «динамическая типизация»

GPath

● GPath аналог XPath, только для любых структур.

● Также есть поддержка Xml

● GPath аналог XPath, только для любых структур.

● Также есть поддержка Xml

Пример

class Person{

String firstName

String lastName

int age

}

def personList = [

new Person(firstName: "dhaval", lastName: "nagar", age: 25),

new Person(firstName: "nachiket", lastName: "patel", age: 24),

]

class Person{

String firstName

String lastName

int age

}

def personList = [

new Person(firstName: "dhaval", lastName: "nagar", age: 25),

new Person(firstName: "nachiket", lastName: "patel", age: 24),

]

Пример

● Можно воспользоваться встроенным функционалом

println personList.collect{it.firstName}

// will print ["dhaval", "nachiket"]

● А можно GPath

println personList.firstName

println personList.firstName.grep(~/d.*/)

// will print ["dhaval"]

● Можно воспользоваться встроенным функционалом

println personList.collect{it.firstName}

// will print ["dhaval", "nachiket"]

● А можно GPath

println personList.firstName

println personList.firstName.grep(~/d.*/)

// will print ["dhaval"]

Пример

def mylinks = """

<links>

<link id="1" url="www.google.com"/>

<link id="2" url="www.apple.co.in"/>

</links>

"""

● Для нахождения ссылок с окончанием "com" и "co.in":

println links.link.@url.grep(~/.*com/)

println links.link.@url.grep(~/.*co[.]in/)

def mylinks = """

<links>

<link id="1" url="www.google.com"/>

<link id="2" url="www.apple.co.in"/>

</links>

"""

● Для нахождения ссылок с окончанием "com" и "co.in":

println links.link.@url.grep(~/.*com/)

println links.link.@url.grep(~/.*co[.]in/)

Groovy builder

● Builder в Groovy позволяет очень легко и быстро создавать сложные иерархические структуры например Xml

● В Groovy уже есть поддержка для Xml (HTML), SWING виджетов, Ant tasks

● Builder в Groovy позволяет очень легко и быстро создавать сложные иерархические структуры например Xml

● В Groovy уже есть поддержка для Xml (HTML), SWING виджетов, Ant tasks

Пример

● Для генерации такой Xml структуры

<person>

<name first="Megan" last="Smith">

<age>32</age>

<gender>female</gender>

</name>

<friends>

<friend>Julie</friend>

<friend>Joe</friend>

<friend>Hannah</friend>

</friends>

</person>

● Для генерации такой Xml структуры

<person>

<name first="Megan" last="Smith">

<age>32</age>

<gender>female</gender>

</name>

<friends>

<friend>Julie</friend>

<friend>Joe</friend>

<friend>Hannah</friend>

</friends>

</person>

Пример

class XMLBuilder{

static void main(String[] args) {

def writer = new StringWriter()

def builder = new groovy.xml.MarkupBuilder(writer)

def friendnames = [ "Julie", "Joey", "Hannah"]

builder.person() {

name(first:"Megan", last:"Smith") {

age("32")

gender("female")

}

friends() {

for (e in friendnames) { friend(e) }

}}

println writer.toString()

}}

class XMLBuilder{

static void main(String[] args) {

def writer = new StringWriter()

def builder = new groovy.xml.MarkupBuilder(writer)

def friendnames = [ "Julie", "Joey", "Hannah"]

builder.person() {

name(first:"Megan", last:"Smith") {

age("32")

gender("female")

}

friends() {

for (e in friendnames) { friend(e) }

}}

println writer.toString()

}}

Integration into Enfinity

Recommended