加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Groovy探索之Map与DSL

发布时间:2020-12-14 16:58:37 所属栏目:大数据 来源:网络整理
导读:???????????????????????????? Groovy 探索之 Map 与 DSL ? ? 在 Java 语言编程中,从 Java5 开始引入了可变参数的概念;引入可变参数的目的,是为了解决形如下面代码的编码冗余。 public class VarArgument { ??? ??? private int a , b , c , d ; ??? ???

???????????????????????????? Groovy探索之MapDSL

?

?

Java语言编程中,从Java5开始引入了可变参数的概念;引入可变参数的目的,是为了解决形如下面代码的编码冗余。

public class VarArgument {

???

??? private int a,b,c,d;

???

???

??? private void p()

??? {

?????? System.out.println(a+","+b+","+c+","+d);

??? }

???

??? public void foo(int a)

??? {

?????? this.a = a;

?????? p();

??? }

???

??? public void foo(int a,int b)

??? {

?????? this.a = a;

?????? this.b = b;

??????

?????? p();

??? }

???

??? public void foo(int a,int b,int c)

??? {

?????? this.a = a;

?????? this.b = b;

?????? this.c = c;

??????

?????? p();

??? }

???

??? public void foo(int a,int c,int d)

??? {

?????? this.a = a;

?????? this.b = b;

?????? this.c = c;

?????? this.d = d;

??????

?????? p();

??? }

???

??? public static void main(String[] args) {

??????

?????? VarArgument va = new VarArgument();

??????

?????? va.foo(1,4);

?

??? }

?

}

?

?

上面的代码中,是一个面向对象编程中的常用的方法重载,目的是为了解决“foo”方法输入参数的个数是可以变化的问题,也就是可变参数的问题。我们可以看到,利用方法重载来解决可变参数的问题,我们需要写出多个方法来做同一件事情,这使得我们的编码效率大大降低。

为了提高编码效率,我们从Java5开始引入了可变参数的概念,通过可变参数上面的代码可以写成下面的样子:

public class VarArgument {

???

??? private int a,d;

???

??? public void foo(int... nums)

??? {

?????? int len = nums.length;

??????

?????? if(len>0) a = nums[0];

??????

?????? if(len>1) b = nums[1];

??????

?????? if(len>2) c = nums[2];

??????

?????? if(len>3) d = nums[3];

??????

?????? //todo

??????

?????? System.out.println(a+","+d);

??? }

???

??? public static void main(String[] args) {

??????

?????? VarArgument va = new VarArgument();

??????

?????? va.foo(1,4);

?

??? }

?

}

?

可以看出,随着Java5引入的可变参数概念,的确使得我们的编码量大大减轻,使得我们朝着敏捷编程的方向在前进。但是,可变参数的引入,仍然有以下三个问题没有解决:一是,可读性的问题,作为VarArgument类的使用者,我们不知道“va.foo(1,4)”中的“1”和“4”代表的含义。二是,参数顺序的问题,比如我们想将1赋给a4赋给b,当然只能严格写成“va.foo(1,4)”,而不能写成“va.foo(4,1)”。三是,灵活性不足,比如,我们只想给a赋值1c赋值3,我们就得写成这样的“va.foo(1,3)”,而不能写成这样“va.foo(1,3)”。

?

为了解决上面的问题,我们在Groovy语言中来使用Map对象作为“foo”方法的参数,请看下面的示例:

class Testor4 {

???

??? private int a,b,c,d

???

??? def foo(Map map)

??? {

?????? this.a = map['a']?map['a']:a

?????? this.b = map['b']?map['b']:b

?????? this.c = map['c']?map['c']:c

?????? this.d = map['d']?map['d']:d

??????

?????? //todo

??????

?????? println "$a,$b,$c,$d"

??? }

?

? static void main(args) {

??? ?

??? ? def t = new Testor4()

??? ?

?????? t.foo([a:1,b:4])

? }

?

}

?

?

可以看到,引入了Map作为参数,我们在Java编程中的可变参数所没有解决的三个问题都得到了解决。

你可能会说,这没有什么啊,Java语言也可以使用Map作为参数啊。是的,Java语言的确可以使用Map作为参数,但Groovy语言对Map参数所做的如下简化,就是Java语言所不及的了。

?

def t = new Testor4()

?

?????? t.foo(a:1,b:4)

???

?

看到了吗?作为“foo”方法的使用者,我们可以完全不知道我们输入的参数是Map类型的,我们只知道把我需要给方法的两个参数ab使用“t.foo(a:1,b:4)”的方式给方法;如果我们只想给ac赋值,则可以使用这样的形式“t.foo(a:1,c:3)”。这真的是在可读性和敏捷性上大大提高。

?

看到了上面的代码,我们立刻会想起我们在GroovyBean中是如何初始化一个对象的。比如有如下一个GroovyBean

?

class Person

{

??? String id

??? String name

??? String age

}

?

?

我们会使用如下的方式来初始化它:

?

?????? def person = new Person(name:'Tom',age:23)

???

?

现在我们就可以知道其中的奥秘了。

正是因为在Groovy语言中使用Map对象作为输入参数大大增强了代码的可读性,我们把它作为DSL编程实现的一种方式。

?

下面,我们使用一个求两点之间的距离的方法来演示使用Map对象作为输入参数的DSL编程方式的例子。

?

?

class Testor5 {

???

??? def length(Map map)

??? {

??????

?????? def fx = map['x1']

??????

?????? def fy = map['y1']

??????

?????? def tx = map['x2']

??????

?????? def ty = map['y2']

??????

?????? return Math.sqrt((fx-tx)*(fx-tx)+(fy-ty)*(fy-ty))

??? }

?

? static void main(args) {

??? ?

??? ? def mc = new ExpandoMetaClass(Integer.class,true)

??????

?????? mc.getM <<

?????? {

?????????? ->

????????????? delegate as float

?????? }

??????

?????? mc.getCm <<

?????? {

?????????? ->

????????????? def cm = delegate as float

????????????? cm/100

?????? }

??????

?????? mc.initialize()

??????

??? ?

??? ? def t = new Testor5()

??? ?

??? ? println t.length(x1:1.m,y1:200.cm,x2:4.m,y2:500.cm)

??? ?

???

?

? }

?

}

?

?

在上面的例子中,我们使用数学坐标来表达点,比如“x1:1.m,y1:200.cm”代表起点,而“1.m”代表1米的地方,“200.cm”代表200厘米。“x2:4.m,y2:500.cm”代表终点的坐标。这种表达法的可读性就非常强,对于“1.m”和“200.cm”这样的表达式,我们在《Groovy探索之运算符的重载 二》里详细的讲过,没看过的可以点击http://blog.csdn.net/hivon/archive/2008/07/15/2651693.aspx

可以看到,“length(x1:1.m,y2:500.cm)”用来表达两点(x1:1.m,y1:200.cm)和(x2:4.m,y2:500.cm)之间的距离,这样的可读性比较好,而且使用Map作为输入参数,实现起来也比较简单。

?

总之,在Groovy语言中使用Map作为输入参数,给我们带来编码的可读性,可以作为DSL的一种实现方式。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读