gray steel drawing compass near brown leather case

Apache Groovy 中 Getter 和 Setter 的基本指南

Getter 和 Setter 在 Java 和 Apache Groovy 中无处不在,但 Groovy 中的开销是…
首页 » 博客 » Apache Groovy 中 Getter 和 Setter 的基本指南

作者:Chris Hermansen

Getter 和 Setter 对于检索和修改外部类变量至关重要。Setter 更新变量值,而 Getter 读取变量值。

Java 的常用用户可能对它们很熟悉。如果您不熟悉,那么当我们深入研究 Apache Groovy 时,您需要了解以下内容。(如果您尚未安装 Groovy,请阅读本系列的介绍。)

“get 概念”(以及相关的“set 概念”)在 Java 中以几种不同的方式出现。一个特别的用途是在 JavaBean 的上下文中,为了实现和强制封装。其工作原理如下

  1. Java 类将字段(也称为属性)定义为仅在该类中已知的内容。
  2. 如果类想要向使用该类的程序公开该字段的值,那么它会提供一个方法来获取属性的值,称为“getter”
  3. 如果类想要允许外部世界调整该类的值,那么它会提供一个方法来设置属性的值,称为“setter”
  4. 通过将存储值的细节与外部世界对该值的访问分离,类可以自由更改值存储的内部实现细节。

这是一个例子。想象一下创建一个表示圆的类。在内部,该类可以存储圆的原点和半径,并提供 getter 来返回原点、半径、直径、面积和周长的值。使用该类的其他程序将不会意识到当前的实现仅存储原点和半径。如果出于某种原因,该类的维护者决定改为存储原点和面积,那么没有任何外部因素会阻碍这种更改。

这是类

 1   import java.lang.*;
 2    public class Groovy03a {
 3    static public void main(String[] args) {
 4        var c = new Circle(1.5d,1.7d,15d);
 5        System.out.println("c area = " + c.getA());
 6        System.out.println("c circumference = " +  c.getC());
 7        c.setA(100.0d);
 8        System.out.println("c area = " + c.getA() + "; radius = " + c.getR());
 9    }
10  }
11    class Circle {
12    private double x, y, r;
13    public Circle(double x, double y, double r) {
14        this.x = x;
15        this.y = y;
16        this.r = r;
17    }
18    public double getX() {
19        return this.x;
20    }
21    public double getY() {
22        return this.y;
23    }
24    public double getR() {
25        return this.r;
26    }
27    public double getA() {
28        return Math.PI * this.r * this.r;
29    }
30    public double getC() {
31        return 2.0d * Math.PI * this.r;
32    }
33    public void setX(double x) {
34        this.x = x;
35    }
36    public void setY(double y) {
37        this.y = y;
38    }
39    public void setR(double r) {
40        this.r = r;
41    }
42    public void setA(double a) {
43        this.r = Math.sqrt(a / Math.PI);
44    }
45    public void setC(double c) {
46        this.r = c / 2.0d / Math.PI;
47    }
48  }

第四行显示创建一个圆,圆心位于 (1.5,1.7),半径为 15.0。

在第五到六行中,使用 getA()getC() getter 方法来查找圆的面积和半径。

在第七行中使用 setA() setter 方法将圆的面积设置为 100.0。您可以在 42-44 行看到,这是通过从提供的面积计算内部存储的半径来实现的。

使用集成开发环境 (IDE)(如 NetBeansEclipse)的程序员依靠他们的 IDE 来帮助编写简单的 getter 和 setter。这意味着他们最终只编写复杂的 getter 和 setter(如上面示例中的 getA()getC()setA()setC())。

Groovy 编程语言对此的处理方式略有不同

  • 类的字段(或属性)默认是私有的,并且会自动生成默认的 getter 和 setter
  • 赋值语句右侧的 c.a 等价于 c.getA()
  • 赋值语句左侧的 c.a 等价于 c.putA(value-on-the-right-hand-side)
  • “手动创建”的 getter 和 setter 也可以通过点号表示法访问。

这是 Groovy 中一个类似的例子,首先展示了与 Java 的等价性(第四到八行),然后使用了点号表示法(第九到十二行)

 1 import java.lang.*;
 2 public class Groovy03a {   
 3     static public void main(String[] args) {
 4         def c = new Circle(1.5d,1.7d,15d)
 5         println "c area = " + c.getA()
 6         println "c circumference = " + c.getC()
 7         c.setA(100.0d)
 8         println "c area = " + c.getA() + "; radius = " + c.getR()
 9         c.x = 2.3d
10         c.y = 1.9d
11         c.a = 225d
12         println "c.x ${c.x} c.y ${c.y} c.r ${c.r} c.a ${c.a} c.c ${c.c}"
13     }
14 }   
15 class Circle {
16     double x, y, r;
17     public Circle(double x, double y, double r) {
18         this.x = x;
19         this.y = y;
20         this.r = r;
21     }
22     public double getA() {
23         return Math.PI * this.r * this.r;
24     }
25     public double getC() {
26         return 2.0d * Math.PI * this.r;
27     }
28     public void setA(double a) {
29         this.r = Math.sqrt(a / Math.PI);
30     }
31     public void setC(double c) {
32         this.r = c / 2.0d / Math.PI;
33     }
34 }

请注意,没有为属性 xyr 声明 getter 或 setter。运行上面的代码,您会看到

$ groovy Groovy03a.groovy
c area = 706.8583470577034
c circumference = 94.24777960769379
c area = 99.99999999999999; radius = 5.641895835477563
c.x 2.3 c.y 1.9 c.r 8.462843753216344 c.a 224.99999999999997 c.c 53.173615527165474
$

Getter 和 Setter 的另一种应用是在列表、映射等中

 1 import java.lang.*;
 2 import java.util.ArrayList;
 3 import java.util.HashMap;
 4 public class Groovy03b {  
 5   static public void main(String[] args) {
 6     var als = new ArrayList<String>();
 7     als.add("Fee");
 8     als.add("Fie");
 9     als.add("Foe");
10     als.add("Fum");
11     System.out.println("als = " + als);
12     System.out.println("als[2] = " + als.get(2));
13     als.set(3, "Foo");
14     System.out.println("als = " + als);
15   }
16 }

要将元素初始放入 ArrayList,请使用 add() 方法,如第 7-10 行所示。然后您可以使用 get()set() 按列表索引检索或设置值。同样,对于映射,您可以使用 get()set() 按键检索或设置值。

编译并运行上面的代码,您会看到

$ java Groovy03b
als = [Fee, Fie, Foe, Fum]
als[2] = Foe
als = [Fee, Fie, Foe, Foo]
$

Groovy 为列表和映射上的这些操作提供了更简洁的语法支持。以下是一些执行相同操作的 Groovy 代码

1 def als = []
2 als << "Fee"
3 als << "Fie"
4 als << "Foe"
5 als << "Fum"
6 println "als = " + als
7 println "als[2] = " + als[2]
8 als[3] = "Foo"
9 println "als = " + als

请注意,这里您只是在创建一个 Groovy 脚本,因此没有类定义和其他类似的干扰。

在第二到五行中,使用 << 运算符,该运算符被重载为 add()

在第七到八行中,您正在使用下标表示法 [n],当它在赋值语句的右侧或左侧时,它分别代替 get()set()

映射也可以使用下标表示法,或者它们可以使用点号表示法引用常量键。也就是说,map["a"]map.a 是等价的。

结论

Getter 和 Setter 以各种形式在 Java 和 Groovy 中无处不在,但与 Java 相比,Groovy 中与它们相关的开销要低得多。

这篇文章是关于 Apache Groovy 系列文章的一部分,请继续关注更多内容.

图片由 Jeff SheldonUnsplash 上提供

作者

如果您喜欢这篇文章,您可能也会喜欢这些