1 类的结构
Groovy 是面向对象编程语言,与 Java 语言类似,都有类、对象、属性、构造函数、成员函数,都有封装、继承、多态三大特性。
1.1 执行顺序
如下,Student 类是一个自定义的类,里面包含了一个类的基本结构。
class Student { private static String tag = "Student" private String name = "zhang san" private int age = 18 static { println("static code, tag=$tag") } { println("non-static code, name=$name") } Student() { // 无参构造函数 println("create-1, name=$name, age=$age") } Student(String name, int age) { // 有参构造函数 println("create-2, name=$name, age=$age") this.name = name this.age = age } void study() { // 成员函数 println("study...") } } def stu1 = new Student() stu1.study() println("-----------------------------------------") def stu2 = new Student("li si", 23)
运行程序后,打印如下。
static code, tag=Student non-static code, name=zhang san create-1, name=zhang san, age=18 study... ----------------------------------------- non-static code, name=li si create-2, name=li si, age=23
类的初始化顺序如下:
父类静态代码块 → 子类静态代码块 → 父类属性初始化 → 父类非静态代码块 → 父类构造函数 → 子类属性初始化 → 子类非静态代码块 → 子类构造函数。
1.2 Setter 和 Getter 方法
class User { String name User(String name) { this.name = name } void setName(String name) { this.name = "xxx_$name" } String getName() { return "yyy_$name" } } User user = new User("zhang san") println(user.@name) // 打印: zhang san println(user.name) // 打印: yyy_zhang san user.@name = "li si" println(user.@name) // 打印: li si println(user.name) // 打印: yyy_li si user.name = "wang wu" println(user.@name) // 打印: xxx_wang wu println(user.name) // 打印: yyy_xxx_wang wu
说明:user.name 调用的是 name 属性的 Setter / Getter 方法,user.@name 是直接修改 / 访问 name 属性。
2 封装
封装是指将相关联的属性和函数封装到同一个类中,并且可以控制这些属性和函数的访问权限,它通过隐藏内部细节和提供清晰的接口,提高了代码的安全性、可维护性和可理解性,它是面向对象编程中的重要概念之一。
在 Groovy 中,有四种访问权限修饰符:private、default、protected 和 public。这些修饰符控制了代码中类、函数、属性等成员的可见性和访问权限。
- private:只能在类内部访问。
- default:如果没有指定访问修饰符,默认为包级私有,只能在同一个包内访问。
- protected:只能在类内部、子类以及同一包内访问。
- public:可以在任何地方访问。
3 继承
继承是指一个类(称为子类或派生类)基于另一个类(称为父类或基类)创建新类,子类继承了父类的属性和函数,并且可以在此基础上进行扩展或修改,它是面向对象编程中的重要概念之一。在 Groovy 中,继承使用 extends 来表示,Object 类是所有类的基类。
class People { String name int age { println("People non-static code, name=$name, age=$age") // 1 } People(String name, int age) { println("People constructor-1, name=$name, age=$age") // 2 this.name = name this.age = age println("People constructor-2, name=$name, age=$age") // 3 } } class Student extends People { int id { println("Student non-static code, name=$name, age=$age, id=$id") // 4 } Student(String name, int age, int id) { super(name, age) println("Student constructor-1, name=$name, age=$age, id=$id") // 5 this.id = id println("Student constructor-2, name=$name, age=$age, id=$id") // 6 } } def stu = new Student("zhang san", 23, 1001)
说明:子类必须直接或间接调用一下父类的一个构造函数,否则编译报错;如果用户没有显式调用父类构造函数,编译后会自动调用父类的无参构造函数,如果父类没有无参构造函数,就会编译报错。
运行程序后,打印如下。
People non-static code, name=zhang san, age=23 People constructor-1, name=zhang san, age=23 People constructor-2, name=zhang san, age=23 Student non-static code, name=zhang san, age=23, id=1001 Student constructor-1, name=zhang san, age=23, id=1001 Student constructor-2, name=zhang san, age=23, id=1001
4 多态
多态是指同一个函数可以在不同的对象上表现出不同的行为,这种行为通常通过继承和接口来实现。多态使得代码更加灵活和可扩展,是面向对象编程中的重要概念之一。
4.1 覆盖函数
class People { String name People(String name) { this.name = name } void say() { println("People say") } } class Student extends People { int id Student(String name, int id) { super(name) this.id = id } @Override void say() { println("Student say") } } People peo = new Student("li si", 1002) peo.say() // 打印: Student say
4.2 类型智能转换
class People { } class Student extends People { void study() { println("study...") } } People peo = new Student() peo.study() // 打印: study...
说明:Java 没有智能转换特性,需要进行强制类型转换。Groovy是一种动态类型语言,它在运行时进行类型检查和方法解析。
5 抽象类(abstract class)
使用 abstract 修饰的类称为抽象类,抽象类中可以有抽象函数,这些函数被添加了 abstract 修饰符,父类不能实现,子类必须重写实现(子类如果也是抽象类除外)。抽象类不能被实例化,只能实例化其具化子类,抽象类中允许有具化的函数。
abstract class People { String name = "xiao min" abstract void say() } class Student extends People { @Override void say() { println("$name: Hello") } } //def peo = new People() // 编译报错, 抽象类不能被实例化 def stu = new Student() stu.say() // 打印: xiao min: Hello
6 接口(interface)
接口与抽象类有些类似,接口里只有常量和抽象函数(函数允许有默认实现),Groovy 中允许一个类实现多个接口,但最多只能继承一个类。
interface A { String x = "xxx" default void aFun() { println("A, x=$x") } } interface B { void bFun() } class C implements A, B { @Override void bFun() { println("bFun") } } def c = new C() c.aFun() // 打印: A, x=xxx c.bFun() // 打印: bFun
运行程序后,打印如下。
A, x=xxx bFun
7 枚举类型(enum)
enum Color { RED("red") { @Override void test() { println("test, $tag") } }, GREEN("green") { @Override void test() { println("test, $tag") } }, BLUE("blue") { @Override void test() { println("test, $tag") } } final String tag Color(String tag) { this.tag = tag } void printColor() { println("color=$tag") } abstract void test() }
声明:本文转自【Groovy】类和对象。