上一篇文章 Groovy入门之语法和变量定义 重点记录的是Groovy的语法以及变量,这一篇文章继续学习Groovy的一些相关知识点。本文的重点是函数和闭包、类和对象,知识点涉及到与Java一样的地方在文章中就不做介绍了,重点将一些与Java不同的地方。另外如果有人接触过JavaScript,相信多数也了解JavaScript中闭包这个概念,但是Groovy中闭包与JavaScript闭包是两个完全不同概念。
有些人可能对函数和方法的叫法一直不太清楚。事实上没有本质区别,在面向过程的语言中一般称为函数,在函数式编程中一般都叫做函数。方法的一般是类的方法,在某一个类中定义的称之为方法。
1.在Groovy中除非指定了确定的返回类型,void也可以作为返回值的一种,否则定义函数必须加上关键字def。
String getString(){ return "hello world" } defgetDef(){ return "hello world" } void printSomething(){ println "hello worlld" } //错误的定义,编译可以通过,但是运行时报错 //getString(){ // return "hello world" //}
2.在定义函数需要传参时可以不设置设置参数的类型,默认是Object类型的,如果用def关键字设置参数类型,事实上也是使用的Object定义参数的。
defprintSomething01(param){ printlnparam } defprintSomething02(int param){ printlnparam } defprintSomething03(defparam){ printlnparam }
3.在调用函数时,如果所定义的函数有参数,在使用的时候可以不使用括号,但是必须得传入参数,参数与函数名以空格隔开。
如果不出入参数必须添加括号,否则代码编译可以通过,但是运行时会出错,会将函数误认为是一个属性。
如果所定义的函数没有参数,在调用的时候必须添加括号,否则运行出错,会将函数误认为是一个属性。
函数调用的时候参数的个数必须匹配,否则也会报错,提示没有定义该函数,如果单个参数除外,可以不用输入参数,系统默认赋值null。
defprintSomething(param01,param02){ printlnparam01+param02 } printSomething ("hello","world")//helloworld printSomething "hello","world"//helloworld //参数个数不对,报错 //printSomething ("hello") defprintOne(param){ printlnparam } printOne()//null
4.函数可以有返回值,如果有显示地使用return关键字,则返回return指定的返回值,其后面的语句不再执行。
如果没有显式地使用return关键字,则返回函数最后一行语句的运行结果。
如果使用void关键字代替def关键字定义函数,则函数的返回值将为null。
defprintSomething(){ return "hello" println "world" } printlnprintSomething()//hello defprintSomething01(){ "hello world" 1 } printlnprintSomething01()//1 defprintSomething02(){ 1 "hello world" } printlnprintSomething02()//hello world
5.支持函数重载,当参数个数不同时,函数名称可以同名。
defprintSomething(param){ printlnparam } defprintSomething(param01,param02){ printlnparam01+" "+param02 } printSomething("hello") printSomething("hello","world")
6.函数内不可以访问函数外的变量
int m=1 def n="hello" //error defprintSomething(){ println m//error println n//error } printSomething()
7.Groovy支持不定长参数。
defprintSomething(... params) { println(params[0]) } printSomething("hello") printSomething("hello","world")
8.函数可以赋值给其它函数,使用语法标记&将函数赋予新的函数。
defprintSomething() { println("hello world") } //printSomething不可以加括号 defprintHello=this.&printSomething printHello()//hello world printSomething()//hello world
在Javascript中闭包的定义:有权访问另外一个函数作用域中的变量的函数。
Groovy中闭包是这么定义的:可以用作函数参数和方法参数的代码块。可以把这个代码块理解为一个函数指针。
闭包的定义格式:
defxxx = { params -> code } //或者 defxxx={code}
在这里可以看出来这里的闭包跟JavaScript中以字面量形式定义对象格式类似。
var obj={username:"admin"} console.log(obj.username);
从这里也可以看出来Groovy中闭包表示形式和闭包跟JavaScript中所讲解的闭包是完全不同的。
1.闭包可以访问外部的变量,记住一点方法是不能访问外部变量的。
defstr="hello world" defclosure={ printlnstr } closure()//hello world
2.闭包调用的方式有两种,闭包.call(参数)或者闭包(参数),在调用的时候可以省略圆括号。
defclosure = { param -> printlnparam } closure("hello world") closure.call("hell call") closure "hello world"
3.闭包是有返回值的,默认最后一行语句就是该闭包的返回值,如果最后一行语句没有不输入任何类型,闭包将返回null。
defclosure = { println "hello world" return "I'm callback" } //hello world //I'm callback printlnclosure() defnoReturn={ println "hello world" } //hello world //null printlnnoReturn()
4.闭包可以有参数,如果没有定义参数,会有一个隐式的默认参数it,如果没有参数可以将[参数]和[->]省略。
如果存在参数,在[->]之前的就是参数,如果只有一个参数,参数可以省略。
闭包中参数名称不能与闭包内或闭包外的参数名重名
defclosure={ println "hello $it" } closure("admin") defclosure={ param01,param02,param03->printlnparam01+param02+param03 } closure "hello","world","ok" defclosure={ printlnit } closure "hello world" //编译时就不通过 //def param //def closure={ // param->println param //}
5.闭包可以作为一个参数传递给另一个闭包,也可以在闭包中返回一个闭包。
deftoTriple = { n -> n * 3 } defrunTwice = { a, c -> c(c(a)) } printlnrunTwice(5, toTriple)//45 deftimes = { x -> { y -> x * y } } printlntimes(3)(4)//12
6.闭包的一些快捷写法,当闭包作为闭包或方法的最后一个参数,可以将闭包从参数圆括号中提取出来接在最后。
如果闭包中不包含闭包,则闭包或方法参数所在的圆括号也可以省略。
对于有多个闭包参数的,只要是在参数声明最后的,均可以按上述方式省略。
defrunTwice = { a, c -> c(c(a)) } printlnrunTwice(5, { it * 3 }) //45 usual syntax printlnrunTwice(5) { it * 3 } //45 defclosure = { param -> printlnparam } closure "hello world" defrunTwoClosures = { a, c1, c2 -> c1(c2(a)) } //when more than one closure as last params assert runTwoClosures(5, { it * 3 }, { it * 4 }) == 60 //usual syntax assert runTwoClosures(5) { it * 3 } { it * 4 } == 60 //shortcut form
7.闭包接受参数的规则,会将参数列表中所有有键值关系的参数,作为一个map组装,传入闭包作为调用闭包的第一个参数。
def f= {m, i, j-> i + j + m.x + m.y } println f(6, x:4, y:3, 7)//20
8.如果闭包的参数声明中没有list,那么传入参数可以设置为list,里面的参数将分别传入闭包参数。
def c = { a, b, c -> a + b + c } deflist = [1, 2, 3] println c(list) // 6
Groovy类与Java类似,在字节码级都被编译成Java类,由于其在定义变量上面的灵活性,所以在新建一个Groovy类时还是有一些不同的,增加了许多灵活性。由于Groovy是松散型语言,它并不强制你给属性、方法参数和返回值定义类型。如果没有指定类型,在字节码级别会被编译成Object。在定义类的属性时不用刻意加上权限修饰符,默认就是public的。
class Book{ deftitle String author private int price public Book(title){ this.title=title } boolean order(int isbn){ true } deftitle(){ "Booke Title" } } Bookbook=new Book("Hello Groovy") book.order(1001) book.title//获取属性 book.title()//访问方法
如果我们将Book类看做是一个JavaBean,事实上Groovy在编译完成后会自动帮助我们生成getter与setter方法,但是私有属性除外也就是说price属性我们不能使用getter与setter方法。
Bookbook=new Book("Hello Groovy") printlnbook.getTitle()//Hello Groovy book.setTitle("New Groovy") printlnbook.getTitle()//New Groovy printlnbook.title////New Groovy
在Groovy中类名和文件名并不需要严格的映射关系,我们知道在Java中主类名必须与文件同名,但是在Groovy中一个文件可以定义多个public类。
在Groovy中可以定义与任何类不相关的方法和语句,这些方法通常称为独立方法或者松方法。
class Hello{ public static String hello(){ return "hello" } } class World{ public static String world(){ return "world" } } printlnHello.hello()+World.world() defhelloWorld(){ return "hello world" }
上面一个文件名定义为Structure.groovy,在这个文件中包含了类的定义和独立方法声明,它编译之后会发生什么呢。首先会生成一个与文件同名的class文件。所有的松语句都集中在run方法中,并且run方法被该类的main方法调用。独立方法被编译成了类的静态方法。与Java相似,每一个独立的类都会被编译成一个单独的class文件。因此编译Structure.groovy文件最后会被编译成Hello.class、World.class和Structure.class。上面一个文件名定义为Structure.groovy,在这个文件中包含了类的定义和独立方法声明,它编译之后会发生什么呢。首先会生成一个与文件同名的class文件。所有的松语句都集中在run方法中,并且run方法被该类的main方法调用。独立方法被编译成了类的静态方法。与Java相似,每一个独立的类都会被编译成一个单独的class文件。因此编译Structure.groovy文件最后会被编译成Hello.class、World.class和Structure.class。
本文地址: www.sunnyang.com/522.html
有关Groovy的学习就先到这里,有关Groovy基础语法的讲解可以参看 Groovy入门之语法和变量定义 这篇博文,两篇文章主要还是偏重中一些基本使用,为的是可以更好的理解应用Android Studio的Gradle工具。笔记的记录基本都是通过浏览别人博客以及《Java脚本编程:语言、框架与模式》这本书,由于个人能力所限,文章中难免有错误疏漏之处,如若发现还望及时指出以求共同进步。
Groovy学习笔记之块、闭包与函数
深入理解Android之Gradle
Groovy基础——Closure(闭包)详解
groovy-闭包
Java脚本编程:语言、框架与模式