前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Groovy 添加带注释的Map构造函数

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

作者头像
白石
发布2019-08-23 10:07:46
1.1K0
发布2019-08-23 10:07:46
举报
文章被收录于专栏:白石白石

添加带注释的Map构造函数

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

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

代码语言:javascript
复制
// 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注释:

代码语言:javascript
复制
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属性:

代码语言:javascript
复制
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属性值:

代码语言:javascript
复制
// 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编写。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 添加带注释的Map构造函数
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档