文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
5.3.6. 委托给任意类型
有可能上述所有方式都无法表示你想要委托的类型。比如,可以定义一个 Mapper
类,它带有一个对象参数,并且定义了一个能够返回其他类型对象的 map
方法:
class Mapper<T,U> { 1⃣️
final T value 2⃣️
Mapper(T value) { this.value = value }
U map(Closure<U> producer) { 3⃣️
producer.delegate = value
producer()
}
}
1⃣️ Mapper
类接受两个通用类型参数:源类型与目标类型。
2⃣️ 源对象保存在一个 final 类型的对象中。
3⃣️ map
方法请求将源对象转换为目标对象。
如你所见, map
上的方法签名并不没有指明是何种对象在受闭包的控制。看看方法体,我们就了解它应该是类型 T
的 value
,但 T
并未在方法签名中,因此没有合适的选项适合 @DelegatesTo
。比如我们打算静态编译下列代码:
def mapper = new Mapper<String,Integer>('Hello')
assert mapper.map { length() } == 5
编译将失败,并且提供了以下失败信息:
Static type checking] - Cannot find matching method TestScript0#length()
在这种情况下,可以使用 @DelegatesTo
注释的 type
成员将 T
引用为类型令牌:
class Mapper<T,U> {
final T value
Mapper(T value) { this.value = value }
U map(@DelegatesTo(type="T") Closure<U> producer) { 1⃣️
producer.delegate = value
producer()
}
}
1⃣️ @DelegatesTo
注释引用了一个方法签名中不存在的基本类型。
注意,这里并不局限于基本类型令牌。 type
成员可以用来表示复杂类型,比如说 List<T>
或 Map<T,List<U>>
。 它之所以被用作最后手段的原因在于,只有当类型检查器发现使用了 @DelegatesTo
之时,类型才被检查,而不是在注释方法本身被编译时才这样做。这就意味着类型安全性只有在调用站点时才能保证。另外,编译起来也比较慢(虽然在绝大多数情况下,这一点并不容易觉察出来)。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论