面向对象官方文档:Object orientation
Groovy支持Java语言规范中定义的所有的基本数据类型:
当Groovy声明并存储一个基本类型字段和变量作为基元,因为它认为一切都是对象,并自动封装成基本类。就像Java所使用的封装器一样。
基本类型封装
Primitive type | 封装类 |
---|---|
boolean | Boolean |
char | Character |
short | Short |
int | Integer |
long | Long |
float | Float |
doublc | Double |
下面是一个使用int的例子:
class Foo {
static int i
}
assert Foo.class.getDeclaredField('i').type == int.class
assert Foo.i != int.class && Foo.i.class == Integer.class
Now you may be concerned that this means every time you use a mathematical operator on a reference to a primitive that you’ll incur the cost of unboxing and reboxing the primitive. But this is not the case, as Groovy will compile your operators into their method equivalents and uses those instead. Additionally, Groovy will automatically unbox to a primitive when calling a Java method that takes a primitive parameter and automatically box primitive method return values from Java. However, be aware there are some differences from Java’s method resolution.
Groovy的类和Java的类非常相似,它们在JVM层面是兼容的。它们都有方法和字段/属性,并且还像Java类一样具有相同的修饰符(public,protected,private,static,etc)
下面列举了一些Groovy类不同于Java的一些关键部分:
下面是一个示例:
class Person {//类的开头,以Person为名
String name
Integer age
def increaseAge(Integer years) { //定义方法
this.age += years
}
}
普通类指的是处于顶层的和具体的类。这意味着它们可以被实例化而无需收到其他类或脚本的限制。这种方式,它们只能是公开的(即使public关键字是受限制的)。类通过使用new关键字调用它们的构造器,如下:
def p = new Person()
内部类被定义在另一个类的内部。这个外部类可以像使用其他类一样使用内部类。另外,一个内部类可以访问外部类的成员,即使它们是私有的。除了外部类的其他类是不能访问内部类的。下面是一个例子:
class Outer {
private String privateStr
def callInnerMethod() {
new Inner().methodA()
}
class Inner {
def methodA() {
println "${privateStr}."
}
}
}
下面是一些使用内部类的原因:
下面的例子,内部类实现了外部类需要的一些接口的方法.下面的代码展示了线程的用法。
class Outer2 {
private String privateStr = 'some string'
def startThread() {
new Thread(new Inner2()).start()
}
class Inner2 implements Runnable {
void run() {
println "${privateStr}."
}
}
}
需要指出的是类Inner2之所以被定义仅仅是为了实现外部类Outer2所需的run方法。
匿名内部类将会消除上例中冗长的代码。
匿名内部类 Anonymous inner class
上一个内部类可以被匿名内部类简化。同样的功能可以被压缩成以下代码:
class Outer3 {
private String privateStr = 'some string'
def startThread() {
new Thread(new Runnable() {//相比于上一个例子,new Inner2()被new Runnable()取代了
void run() {
println "${privateStr}."
}
}).start() //start方法像平常一样被调用
}
}
抽象类代表了一般概念,也就是说,不可以被实例化,创建派生子类。它们的成员包含字段/属性和抽象方法或者具体方法。抽象方法没有被实现,但必须被具体的子类所实现。
abstract class Abstract {//抽象类必须用关键字abstract声明
String name
abstract def abstractMethod() //抽象方法的声明也必须用到abstract
def concreteMethod() {
println 'concrete'
}
}
抽象类通常与接口对比。但至少有两个重要的不同。第一,抽象类可能会包含字段/属性和具体方法,接口可包含抽象方法。并且,一个类可以实现多个接口,而其职能继承一个类,无论这个类是抽象的还是具体的。
接口定义的规范类必须遵守。一个接口只定义一系列的需要被实现的方法,但是不定义具体的方法实现。
interface Greeter { //接口使用interface关键字声明
void greet(String name) //只定义方法头
}
接口的方法总是public的。在接口中使用protected 或者private修饰方法是错误的。
interface Greeter {
protected void greet(String name)//将会造成编译时错误
}
一个类实现接口的所有的方法
class SystemGreeter implements Greeter {
void greet(String name) {
println "Hello $name"
}
}
def greeter = new SystemGreeter()
assert greeter instanceof Greeter//任何SystemGreeter的实例也是即可Greeter的实例
一个接口可以继承另一个接口:
interface ExtendedGreeter extends Greeter {//ExtendedGreeter接口继承Greeter接口使用extends关键字
void sayBye(String name)
}
需要指出的是,一个类实现一个接口,必须是显式的。例如,下面这个类定义了一个geet方法正如在Greeter接口中声明的一样,但这个类并没有声明Greeter是其接口:
class DefaultGreeter {
void greet(String name) { println "Hello" }
}
greeter = new DefaultGreeter()
assert !(greeter instanceof Greeter)
换句话说,Groovy没有定义结构形态(我的理解是没有定义结构相同就是形成了实现关系)。然而在运行时可以通过使用as强制转换符可以使得一个对象实现一个接口:
greeter = new DefaultGreeter()//创建一个没有实现接口的DefaultGreeter类的对象
coerced = greeter as Greeter //在运行时强转Greeter对象
assert coerced instanceof Greeter //强转的实例实现了Greeter接口
You can see that there are two distinct objects: one is the source object, a DefaultGreeter instance, which does not implement the interface. The other is an instance of Greeter that delegates to the coerced object.
Groovy interfaces do not support default implementation like Java 8 interfaces. If you are looking for something similar (but not equal), traits are close to interfaces, but allow default implementation as well as other important features described in this manual.