第七章 groovy风格的动态面向对象

7.1 定义类和脚本

7.1.1 定义属性和本地变量

变量的声明

属性和本地变量在使用之前必须进行声明(除了脚本之外),这有助于实施作用域规则和防止程序员偶然的拼写错误。


脚本允许使用没有声明的变量,在这种情况下变量被假定从脚本的 binding 属性获取,如果在 binding 中没有发现相应的变量,那么把变量增加到binding中,binding是一个数据存储器,它能把变量在脚本调用者和脚本之间进行传递。


缺省属性范围在 groovy 有特殊的意思,在没有指定范围修饰符的属性声明的时候,groovy会根据需要生成相应的访问方法(getter 方法和 setter 方法)。

定义变量的类型是可选的, 当没有类型和修饰符时,必须使用 def 来作为替换,实际上用 def 来表明属性或者变量是没有类型的(尽管在内部将被声明为 Object 类型)
指定了类型的引用必须符合给定的类型

引用属性和取消对属性的引用 

除了可以通过 obj.fieldName 来引用属性之外,也可以通过下标操作符来引用属性

重写下标操作符:
Object get (String name) 
void set (String name, Object value) 
重写 get 方法意味着重写了 dot-fieldName 操作符,重写 set 方法意味着重写了 field assignment 操作符。
语句 x.z.y=something 这个语句执行的结果是什么?这与 getX().getY().setZ(somethine)等价

7.1.2 方法和参数

通常能使用 java 修饰符;返回类型的声明是可选的;如果没有修饰符或者返回类型,那么使用 def 关键字来填空白,当使用 def关键字的时候,方法的返回类型被认为是没有类型(尽管没有返回类型,这时与 void 方法等价),在这种情况下,groovy 将方法的返回类型定义为 java.lang.Object, 缺省的方法访问范围为 public
方法分派
package groovyInAction.seven

class Example7_5DeclaringMethods {
	static void main(String[] args) {
		def some = new Example7_5DeclaringMethods()
		some.publicVoidMethod()
		assert 'hi' == some.publicUntypeMethod()
		assert 'ho' == some.publicTypeMethod()
		combineMethod()	
	}
	
	void publicVoidMethod(){}
	
	def publicUntypeMethod(){
		return 'hi'
	}
	 def publicTypeMethod(){
		 return 'ho'
	 }
	 
	 protected static final void combineMethod(){}
}
main 方法 args 目前的类型隐式为 java.lang.Object
显式声明参数的类型是可选的,当声明类型被忽略的时候,groovy 使用 Object 作为类型,可以顺序的使用多个参数,通过逗号进行分隔
package groovyInAction.seven

class Example7_6DeclaringParameterLists {
	static void main(args){
		assert 'untyped' == method(1)
		assert 'typed' == method('whatever')
		assert 'two args' == method(1,2)
	}
	static method(arg){
		return 'untyped'
	}
	static method(String arg){//方法重载
		return 'typed'
	}
	static method(arg1,Number arg2){
		return 'two args'
	}
}

所有方法调用都与方法参数的位置有关,这意味做每一个参数已经根据它参数列表中的位置被决定了。对于复杂的脚本有一些痛苦的缺点:
你必须记住真实的参数的顺序,当参数列表比较长时这增加了难度;
对于非传统的脚本使用,如果根据不同的信息调用方法是有意义,那么需要构建很多不同的方法来处理这些差异,这很快就变得笨重起来并且导致方法的难以维护,特别是当有些参数是可选的时候,如果许多可选的参数具有相同的类型,这会变得特别困难。

注意:每当谈论到命名的参数的时候,我们的意思是map的key在方法中被用作参数被调用,从一个程序员的视角看,这看起来就像原生的命名参数的支持,但其实不是这样的,这种技巧是必须的,因为JVM不支持把参数的名称保存在字节码中。
package groovyInAction.seven

class Example7_7AdvancedParameterUsages {
	static main(args){
		def summer = new Summer()
		assert 2 == summer.sumWithDefaults(1, 1)
		assert 3 == summer.sumWithDefaults(1, 1,1)
		
		
		assert 2 == summer.sumWithList([1,1])
		assert 3 == summer.sumWithList([1,1,1])
		assert 2 == summer.sumWithOptionals(1,1)
		assert 3 == summer.sumWithOptionals(1,1,1)
		
		assert 2 == summer.sumNamed(a:1,b:1)
		assert 3 == summer.sumNamed(a:1,b:1,c:1)
		assert 1 == summer.sumNamed(c:1)
	}
}
class Summer{
	def sumWithDefaults(a, b, c=0){ //Explicit arguments and a default value
		return a + b + c		
	}
	def sumWithList(List args){ //Define arguments as a list
		return args.inject(0) {sum,i -> sum +=i}
	}
	
	def sumWithOptionals(a,b,Object[] optionals){//Optional arguments as an array
		return a + b + sumWithList(optionals.toList())
	}
	def sumNamed(Map args){//Define arguments as a map
		['a','b','c'].each{ args.get(it,0)}
		return args.a + args.b + args.c
	}

}
注意:实现可变长度的参数列表的第二种方式是,你可以覆盖groovy的分派方法invokeMethod(name,params[]),这是每个GroovyObject对象都提供的方法。

高级命名

objectReferenct.'my.method-Name'
这个特性的目的是支持把调用方法的名称变成函数的一部分,通常情况下不直接使用这个特性,但是groovy的其他部分将使用到这个特性。
obj."${var}"()

7.1.3 安全的引用符号(?.)

package groovyInAction.seven

class Example7_8ProtectingFromNullPointerExceptionsUsingTheOperator {
	static main(args){
		def map = [a:[b:[c:1]]]
		
		assert map.a.b.c == 1
		
		if(map && map.a && map.a.x){//protect with if:short-circuit evaluation
			assert map.a.x.c == null
		}
		
		try{//Protect with try/catch
			assert map.a.x.c == null
		}catch(NullPointerException npe){
		}
		
		
		assert map?.a?.x?.c == null //Safe dereferencing
	}
}

7.1.4 构造器(构造方法)






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值