Groovy中的面向对象
Groovy中的面向对象
前面说到groovy支持脚本和类,前面一节已将简单说了脚本和类之间的关系,这一节主要介绍一下groovy中类的相关知识,即面向对象相关知识。
1.类型
1.1 原始类型
groovy中支持的原始数据类型与java相同,分别是boolean,char,short,int,long,float,double。
1.2 类
groovy中的类与java中很相似,但有以下几点是groovy特有的:
public
修饰的字段会被自动转换成属性变量,这样可以避免很多冗余的get和set方法。- 如果属性或方法没有访问权限修饰符,那么默认是public,而java中是proteced。
- 类名不需要和文件名相同。
- 一个文件中可以定义多个一级类。如没有定义类,则这个groovy文件被认为是脚本文件。
1.2.1 普通类
groovy的普通类和java类似,使用new关键字获得实例。
1.2.2 内部类
内部类也基本类似,下面给一个例子:
class Outer2 {
private String privateStr = 'some string'
def startThread() {
new Thread(new Inner2()).start()
}
class Inner2 implements Runnable {
void run() {
println "${privateStr}."
}
}
}
1.2.3 抽象类
抽象类也与java基本类似:
abstract class Abstract {
String name
abstract def abstractMethod()
def concreteMethod() {
println 'concrete'
}
}
1.3 接口
groovy的接口和java也基本类似,支持接口继承接口。
1.4 构造方法
groovy的构造方法和java就有略微不同了,groovy的构造方法支持位置参数
和命名参数
,下面具体看。
1.4.1 位置参数构造方法
位置构造参数跟java中的通常构造方法类似,不同位置的参数具有不同的含义。如下:
class PersonConstructor {
String name
Integer age
PersonConstructor(name, age) {
this.name = name
this.age = age
}
}
def person1 = new PersonConstructor('Marie', 1)
def person2 = ['Marie', 2] as PersonConstructor
PersonConstructor person3 = ['Marie', 3]
具体调用构造方法的时候groovy多了两种写法。因为位置已经固定,所以即使PersonConstructor person3 = ['Marie', 3]
这样的写法groovy也能从内部给你做初始化。
1.4.2 命名参数构造方法
命名参数构造方法不需要用户定义,当一个类没有构造方法的时候,其默认有一个命名参数构造方法。
class PersonWOConstructor {
String name
Integer age
}
def person4 = new PersonWOConstructor()
def person5 = new PersonWOConstructor(name: 'Marie')
def person6 = new PersonWOConstructor(age: 1)
def person7 = new PersonWOConstructor(name: 'Marie', age: 2)
1.5 方法
定义groovy的方法也很简单,可使用关键字def
或者返回值就行。groovy中的方法都有返回值,如果没有写return
语句,groovy会计算方法中的最后一行语句并将其结果返回。
下面是四种不同的方法定义:
def someMethod() { 'method called' }
String anotherMethod() { 'another method called' }
def thirdMethod(param1) { "$param1 passed" }
static String fourthMethod(String param1) { "$param1 passed" }
1.5.1 方法的命名参数
在自定义的方法中要使用命名参数的话,就要使用Map作为唯一参数,如下:
def foo(Map args) { "${args.name}: ${args.age}" }
foo(name: 'Marie', age: 1)
1.5.2 方法的默认参数
groovy方法支持默认参数,这样就是的其参数变得可选,当参数没有被填入,则会使用默认参数:
def foo(Map args) { "${args.name}: ${args.age}" }
foo(name: 'Marie', age: 1)
1.5.3 方法的可变长参数
这个在java中也是存在的,举个简单的例子:
def foo(Map args) { "${args.name}: ${args.age}" }
foo(name: 'Marie', age: 1)
1.6 注解
groovy中的注解跟java中的类似,但又比java中多了一些特性,下面简单介绍一下。
1.6.1 注解的闭包参数
在groovy中,有一个有趣的语言特性就是可以使用闭包
作为注解的参数值。这样的注解一般在什么情况下使用呢?举个简单的例子,有些时候软件的运行时依赖其运行的环境和操作系统的,针对不同的环境或系统,表现也不一样。看一下这个例子:
class Tasks {
Set result = []
void alwaysExecuted() {
result << 1
}
@OnlyIf({ jdk>=6 })
void supportedOnlyInJDK6() {
result << 'JDK 6'
}
@OnlyIf({ jdk>=7 && windows })
void requiresJDK7AndWindows() {
result << 'JDK 7 Windows'
}
}
Tasks类用于完成alwaysExecuted
,supportedOnlyInJDK6
,requiresJDK7AndWindows
这三个任务,但不同的任务对环境和系统的要求都不一样,这里使用@OnlyIf
来表明对环境和系统的需求。
@Retention(RetentionPolicy.RUNTIME)
@interface OnlyIf {
Class value()
}
在groovy中如果需要让注解接受闭包的话,只需要像上面这样定义一个Class类型的value值。这样OnlyIf就可以接受闭包作为其值了。
接着写处理类:
class Runner {
static <T> T run(Class<T> taskClass) {
def tasks = taskClass.newInstance()
def params = [jdk:6, windows: false]
tasks.class.declaredMethods.each { m ->
if (Modifier.isPublic(m.modifiers) && m.parameterTypes.length == 0) {
def onlyIf = m.getAnnotation(OnlyIf)
if (onlyIf) {
Closure cl = onlyIf.value().newInstance(tasks,tasks)
cl.delegate = params
if (cl()) {
m.invoke(tasks)
}
} else {
m.invoke(tasks)
}
}
}
tasks
}
}
和java类似,通过反射拿到Task对象的方法,接着获取其OnlyIf注解,如果获取成功,则提取OnlyIf的闭包进行调用。
2 Traits(特征)
trait是groovy中独有的面向对象的语法特性,他具备如下功能:
- 行为构成
- 运行时的接口实现
- 行为重载
- 兼容静态类型的检查和编译
Trait可以被看作是具有方法实现和状态的接口,使用trait
关键字定义:
trait FlyingAbility {
String fly() { "I'm flying!" }
}
上面就定义了一个飞行能力的特证,它的使用方法和接口一样,都是使用implements
关键字:
class Bird implements FlyingAbility {}
def b = new Bird()
assert b.fly() == "I'm flying!"
这个看上去感觉跟继承有点类似,但又不一样,trait仅仅是将其方法和状态嵌入到实现类中,而没有继承中的那种上下级的父子关系。
trait中的一些语法特性:
- trait中支持定义抽象方法,其实现类必须实现此抽象方法。
- trait中可以定义私有方法,其实现类无法访问。
- trait中的this关键字指其实现类。
- trait可以实现接口。
- trait中可定义属性,此属性会自动被附加到实现此trait的类中。
- trait可定义私有字段由于存储相关状态。
- trait可定义公共字段,但为了避免
钻石问题
,其获取方式有所不同,如下:
trait Named {
public String name
}
class Person implements Named {}
def p = new Person()
p.Named__name = 'Bob'
- 第一个类可以实现多个trait。
- 实现类可重写trait中的默认方法。
- trait可以继承另一个trait使用关键字extends,若要继承多个则使用implements关键字。
- 可以在运行时动态实现trais,使用关键字as。
以上简单介绍了groovy中面向对象的相关知识,更详细的资料请参考官方文档
Groovy中的面向对象的更多相关文章
- 前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型
前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型 前言(题外话): 有人说拖延症是一个绝症,哎呀治不好了.先不说这是一个每个人都多多少少会有的,也不管它究竟对生活有多么大的 ...
- 简单分析JavaScript中的面向对象
初学JavaScript的时候有人会认为JavaScript不是一门面向对象的语言,因为JS是没有类的概念的,但是这并不代表JavaScript没有对象的存在,而且JavaScript也提供了其它的方 ...
- 前端开发:面向对象与javascript中的面向对象实现(一)
前端开发:面向对象与javascript中的面向对象实现(一) 前言: 人生在世,这找不到对象是万万不行的.咱们生活中,找不到对象要挨骂,代码里也一样.朋友问我说:“嘿,在干嘛呢......”,我:“ ...
- Java语言中的面向对象特性总结
Java语言中的面向对象特性 (总结得不错) [课前思考] 1. 什么是对象?什么是类?什么是包?什么是接口?什么是内部类? 2. 面向对象编程的特性有哪三个?它们各自又有哪些特性? 3. 你知 ...
- 浅谈Objective—C中的面向对象特性
Objective-C世界中的面向对象程序设计 面向对象称程序设计可能是现在最常用的程序设计模式.如何开发实际的程序是存在两个派系的-- 面向对象语言--在过去的几十年中,很多的面向对象语言被发明出来 ...
- Java中的面向对象
Java中的面向对象 在软件开发的学习中, 我最先接触的开发语言就是java,但都是简单的函数和循环数组的应用.说道面向对象,第一次看到这个词的时候还是在C#的学习过程中,我记得当时PPT上霸气的解释 ...
- Groovy中那些神奇注解之InheritConstructors
上一篇:Groovy中那些神奇注解之ToString 写完ToString,本来想今天就写到这了,突然觉得InheritConstructors注解实在也是个神器,写起来也没多少字,还是写了吧. In ...
- Groovy中那些神奇注解之ToString
继续上一篇:Groovy中那些神奇注解之Memoized 这篇就讲讲@groovy.transform.ToString这个注解,这注解太熟悉了,熟悉到让人一看就知道是干吗的,不就是把Bean转在St ...
- Groovy中那些神奇注解之Memoized
临近年关手头比较闲,去看了一下Groovy的官方文档,才发现原来Groovy中带了那么多的注解,很多注解带来的效果,有时候让人感觉“这不是在变魔法吧”. 个人很喜欢Groovy,写不成Ruby,Gro ...
随机推荐
- Oracle 10g通过创建物化视图实现不同数据库间表级别的数据同步
摘自:http://blog.csdn.net/javaee_sunny/article/details/53439980 目录(?)[-] Oracle 10g 物化视图语法如下 实例演示 主要步骤 ...
- fprintf宏
最近在调试程序,使用printf函数和调试信息都不能在终端输出,所以使用比较笨的方法.将调试信息写到文件中,再查看文件.由于要多次使用fprintf函数,所以将其写成宏. 参考链接: http://w ...
- Understanding the difficulty of training deep feedforward neural networks
本文作者为:Xavier Glorot与Yoshua Bengio. 本文干了点什么呢? 第一步:探索了不同的激活函数对网络的影响(包括:sigmoid函数,双曲正切函数和softsign y = x ...
- Unity3D深入浅出 -创造 物理材质(Physics Materials)
在Unity3d中已经配置好了5种常用的物理材质,Bouncy.Ice.Metal.Rubber.Wood,在菜单中依次选择Assets - Import Package - Physics Mate ...
- php -- realpath($path) 函数
PHP realpath路径函数会检测$path指向的目标文件(或文件夹)是否真实存在,相当于调用了file_exists($path). 1.如果目标文件存在且不是符号连接(linux下俗称“软链接 ...
- XML 入门
XML语法 所有 XML 元素都须有关闭标签 XML 标签对大小写敏感 XML 必须正确地嵌套 XML 文档必须有根元素 就像HTML一样,HTML必须有<html>根元素.XML也必须有 ...
- 关于lockkeyword
线程同步对象keywordlock,是以lock相应的object对象为准,即随意线程lock住lockObj对象之后,其它线程不管在其它不论什么代码段使用lock(lockObj)去进行线程同步时, ...
- endl的读法
endl是“end line”的缩写,所以它应该念作“endELL”而不是“endONE”.
- 【Java面试题】49 垃圾回收的优点和原理。并考虑2种回收机制。
1.Java语言最显著的特点就是引入了垃圾回收机制,它使java程序员在编写程序时不再考虑内存管理的问题. 2.由于有这个垃圾回收机制,java中的对象不再有“作用域”的概念,只有引用的对象才有“作用 ...
- UVa 10450 - World Cup Noise
题目:构造一个01串,使得当中的1不相邻,问长度为n的串有多少中. 分析:数学,递推数列. 设长度为n的串有n个.则有递推关系:f(n)= f(n-1)+ f(n-2): 长度为n的结束可能是0或者1 ...