Groovy 添加带注释的Map构造函数

添加带注释的Map构造函数

从Groovy的早期开始,我们可以创建POGO(Plain Old Groovy Objects)类,它们将具有带有Map参数的构造函数。 Groovy在生成的类中自动添加构造函数。我们可以使用命名参数来创建POGO的实例,因为Map参数构造函数。 这只有在我们不添加自己的构造函数且属性不是最终的时才有效。从Groovy 2.5.0开始,我们可以使用@MapConstrutor AST转换注释来添加带有Map参数的构造函数。使用注释我们可以有更多选项来自定义生成的构造函数。例如,我们可以让Groovy使用Map参数生成构造函数,并添加我们自己的构造函数。 属性也可以是final,我们仍然可以使用带有Map参数的构造函数。

首先,我们在创建POGO时查看Groovy中的默认行为:

// Simple POGO.
// Groovy adds Map argument
// constructor to the class.
class Person {
    String name
    String alias
    List<String> likes
}
 
// Create Person object using
// the Map argument constructor.
// We can use named arguments,
// with the name of key being
// the property name. Groovy
// converts this to Map.
def mrhaki =
    new Person(
        alias: 'mrhaki',
        name: 'Hubert Klein Ikkink',
        likes: ['Groovy', 'Gradle'])
         
assert mrhaki.alias == 'mrhaki'
assert mrhaki.name == 'Hubert Klein Ikkink'
assert mrhaki.likes == ['Groovy', 'Gradle']
 
 
// Sample class with already
// a constructor. Groovy cannot
// create a Map argument constructor now.
class Student {
    String name
    String alias
     
    Student(String name) {
        this.name = name
    }
}
 
 
import static groovy.test.GroovyAssert.shouldFail
 
// When we try to use named arguments (turns into a Map)
// in the constructor we get an exception.
def exception = shouldFail(GroovyRuntimeException) {
    def student =
        new Student(
            name: 'Hubert Klein Ikkink',
            alias: 'mrhaki')
}
 
assert exception.message.startsWith('failed to invoke constructor: public Student(java.lang.String) with arguments: []')
assert exception.message.endsWith('reason: java.lang.IllegalArgumentException: wrong number of arguments')

现在让我们在下一个例子中使用@MapConstructor注释:

import groovy.transform.MapConstructor
 
@MapConstructor
class Person {
    final String name // AST transformation supports read-only properties.
    final String alias
    List<String> likes
}
 
// Create object using the Map argument constructor.
def mrhaki =
    new Person(
        name: 'Hubert Klein Ikkink',
        alias: 'mrhaki',
        likes: ['Groovy', 'Gradle'])
         
assert mrhaki.name == 'Hubert Klein Ikkink'
assert mrhaki.alias == 'mrhaki'
assert mrhaki.likes == ['Groovy', 'Gradle']
 
// Using the annotation the Map argument
// constructor is added, even though we
// have our own constructor as well.
@MapConstructor
class Student {
    String name
    String alias
     
    Student(String name) {
        this.name = name
    }
}
 
def student =
    new Student(
        name: 'Hubert Klein Ikkink',
        alias: 'mrhaki')
         
assert student.name == 'Hubert Klein Ikkink'
assert student.alias == 'mrhaki'

AST转换支持几个属性。 我们可以使用属性includesexcludes来包含或排除将在Map参数构造函数中获取值的属性。 在下面的例子中,我们看到了如何使用includes属性:

import groovy.transform.MapConstructor
 
@MapConstructor(includes = 'name')
class Person {
    final String name
    final String alias
    List<String> likes
}
 
// Create object using the Map argument constructor.
def mrhaki =
    new Person(
        name: 'Hubert Klein Ikkink',
        alias: 'mrhaki',
        likes: ['Groovy', 'Gradle'])
         
assert mrhaki.name == 'Hubert Klein Ikkink'
assert !mrhaki.alias
assert !mrhaki.likes

我们可以使用属性prepost通过AST转换添加在生成的代码之前或之后执行的自定义代码。 我们使用需要执行的代码为这些属性分配一个Closure

在下一个示例中,我们使用代码设置pre属性,如果未通过构造函数设置,则该代码计算alias属性值:

// If alias is set in constructor use it, otherwise
// calculate alias value based on name value.
@MapConstructor(post = { alias = alias ?: name.split().collect { it[0] }.join() })
class Person {
    final String name // AST transformation supports read-only properties.
    final String alias
    List<String> likes
}
 
// Set alias in constructor.
def mrhaki =
    new Person(
        name: 'Hubert Klein Ikkink',
        alias: 'mrhaki',
        likes: ['Groovy', 'Gradle'])
         
assert mrhaki.name == 'Hubert Klein Ikkink'
assert mrhaki.alias == 'mrhaki'
assert mrhaki.likes == ['Groovy', 'Gradle']
 
// Don't set alias via constructor.
def hubert =
    new Person(
        name: 'Hubert A. Klein Ikkink')
         
assert hubert.name == 'Hubert A. Klein Ikkink'
assert hubert.alias == 'HAKI'
assert !hubert.likes

用Groovy 2.5.0编写。

转载于:https://my.oschina.net/wstone/blog/3094875

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值