Groovy之Hook Method钩子方法
ProjectDaedalus
共 15148字,需浏览 31分钟
· 2022-06-20
一般情况下当我们访问或修改不存在的属性、调用不存在的方法会抛出异常,而在Groovy中则可以通过实现相应的Hook Method钩子方法以避免异常发生
属性缺失
Groovy在MP元编程方面提供了丰富的特性,其中之一就是在访问、修改不存在的属性时,提供了一个钩子方法。下面即是一个简单的Groovy示例,当我们访问、修改Tiger类不存在的属性,即会抛出相应的异常
class MissPropertyDemo {
static void testTiger() {
Tiger tiger = new Tiger(name: "Tony", type: "TIGER")
assert tiger.name == "Tony"
assert tiger.type == "TIGER"
try {
// 访问不存在的属性
def age = tiger.age
} catch (Exception e) {
assert e instanceof MissingPropertyException
println("Happen Missing Property Exception #1")
}
try {
// 修改不存在的属性
tiger.age = 234
} catch (Exception e) {
assert e instanceof MissingPropertyException
println("Happen Missing Property Exception #2")
}
try {
// 访问不存在的静态属性
def remark = Tiger.remark
} catch (Exception e) {
assert e instanceof MissingPropertyException
println("Happen Missing Property Exception #3")
}
try {
// 修改不存在的静态属性
Tiger.remark = 234
} catch (Exception e) {
assert e instanceof MissingPropertyException
println("Happen Missing Property Exception #4")
}
}
}
class Tiger{
String name
String type
}
测试结果如下所示
而由于Groovy为属性缺失这一场景提供了相应了钩子方法:propertyMissing、$static_propertyMissing。以避免直接抛出相应的异常,示例代码如下所示
class MissPropertyDemo {
static void testLion() {
Lion lion = new Lion(name: "Tom", type: "LION")
assert lion.name == "Tom"
assert lion.type == "LION"
// 访问不存在的属性
def result = lion.age
assert result == "Not age Property For Get!"
// 修改不存在的属性
lion.age = 22
// 访问不存在的静态属性
result = Lion.remark
assert result == "Not remark Static Property For Get!"
// 修改不存在的静态属性
Lion.remark = "危险动物"
}
}
class Lion{
String name
String type
/**
* 实现访问不存在的属性的钩子函数
* @param propertyName
* @return
*/
def propertyMissing(String propertyName) {
return "Not ${propertyName} Property For Get!"
}
/**
* 实现修改不存在的属性的钩子函数
* @param propertyName
* @param args
*/
void propertyMissing(String propertyName, Object args) {
println "Not ${propertyName} Property! For Set, args: ${args}"
}
/**
* 实现访问不存在的静态属性的钩子函数
* @param propertyName
* @return
*/
static def $static_propertyMissing(String propertyName) {
return "Not ${propertyName} Static Property For Get!"
}
/**
* 实现修改不存在的静态属性的钩子函数
* @param propertyName
* @param args
*/
static void $static_propertyMissing(String propertyName, Object args) {
println "Not ${propertyName} Static Property For Set, args: ${args}"
}
}
测试结果如下所示,符合预期
方法缺失
当我们调用一个不存在的方式时,即会抛出异常
class MissMethodDemo {
/**
* 调用不存在的方法, 抛出异常
*/
static void testCat() {
Cat cat = new Cat(name:"Tom", type:"CAT")
try {
// 调用实例不存在的方法
cat.fly()
} catch (Exception e) {
assert e instanceof MissingMethodException
println("Happen Missing Method Exception #1")
}
try {
// 调用不存在的静态方法
Cat.run()
} catch (Exception e) {
assert e instanceof MissingMethodException
println("Happen Missing Method Exception #2")
}
}
}
class Cat {
String name
String type
}
测试结果如下,符合预期
对于非静态方法而言,我们可以实现methodMissing方法以避免抛出异常。示例代码如下所示
class MissMethodDemo {
/**
* 调用不存在的方法, 返回默认值
*/
static void testDog() {
Dog dog = new Dog(name:"Aaron", type:"DOG")
// 调用实例不存在的方法
String msg = dog.fly("5", "km")
assert msg == "[DOG] ==>> methodName: fly, args: [5, km]"
}
}
class Dog {
String name
String type
/**
* 实现方法缺失的钩子函数
* @param methodName
* @param args
* @return
*/
def methodMissing(String methodName, Object args) {
return "[DOG] ==>> methodName: ${methodName}, args: ${args}"
}
}
对于静态方法而言,我们可以实现$static_methodMissing方法以避免抛出异常。示例代码如下所示
class MissMethodDemo {
/**
* 调用不存在的静态方法
*/
static void testChicken() {
assert Chicken.getInfo() == "I'm a CHICKEN"
assert Chicken.calcPrice() == "Missing Static Method: calcPrice"
}
}
class Chicken {
static String type = "CHICKEN"
static String getInfo() {
return "I'm a ${type}"
}
/**
* 实现静态方法缺失的钩子函数$static_methodMissing, 以避免抛出MissingMethodException异常
* @param methodName
* @param args
* @return
*/
static def $static_methodMissing(String methodName, Object args) {
return "Missing Static Method: $methodName"
}
}
与此同时,我们还可以通过invokeMethod方法进行动态选择的方法调用,示例代码如下所示
class MissMethodDemo {
/**
* 调用不存在的方法, 动态处理
*/
static void testPig() {
Pig pig = new Pig(name:"Bob", type:"PIG")
// 调用实例不存在的方法
def result1 = pig.swim()
assert result1 == "Yes, Bob can Swim..."
// 调用实例不存在的方法
def result2 = pig.fly()
assert result2 == "Yes, Bob also can Fly~"
// 调用实例不存在的方法
def result3 = pig.eat()
assert result3 == null
}
}
class Pig {
String name
String type
String swimmable() {
return "Yes, ${name} can Swim..."
}
String flyable() {
return "Yes, ${name} also can Fly~"
}
/**
* 实现方法缺失的钩子函数
* @param methodName
* @param args
* @return
*/
def methodMissing(String methodName, Object args) {
// 新方法名
String newMethodName
switch (methodName) {
case "swim" : {
newMethodName = methodName + "mable"
break
}
case "fly" : {
newMethodName = methodName + "able"
break
}
default : newMethodName = null
}
if(newMethodName) {
def result = this.invokeMethod( newMethodName, null )
return result
}
return null
}
}
参考文献
Groovy In Action · 2nd Edition Dierk König、Guillaume Laforge著
评论
.NET 开源工具库,集成超过1000个扩展方法
前言推荐一个.NET 开源项目,集成了超过1000个扩展方法。项目简介Z.ExtensionMethods是由zzzprojects公司开发并维护的一款开源库,为.NET开发人员提供一系列实用的扩展方法,可以减少重复劳动、提高开发效率,支持.NET Framework 和 .NET Core。该项目
dotNET全栈开发
10
带你玩转Linux系统之lscpu命令
链接:https://bbs.huaweicloud.com/blogs/422603一、lscpu命令介绍lscpu 是一个 Linux 命令,用于显示CPU架构的详细信息。它可以用来查看 CPU 的型号、主频、架构、虚拟化支持等。二、lscpu命令的使用帮助2.1 命令格式lscpu [选项]2
良许Linux
0
C语言基础之动态内存操作汇总
来源:机器之心1、堆区空间申请#include <stdlib.h> //头文件void *malloc(size_t size);//函数size表示申请的空间字节数函数的返回值:成功:返回值空间起始地址失败:NULL特点:分配指定大小的内存空间;分配的内存空间是连续的;需要手动释放
良许Linux
0
大模型并行训练指南:通俗理解Megatron-DeepSpeed之模型并行与数据并行(下)
文末《大模型项目开发线上营》秒杀倒计时↓↓↓接前文:(上)篇>>>大模型并行训练指南:通俗理解Megatron-DeepSpeed之模型并行与数据并行(上)(中)篇>>>大模型并行训练指南:通俗理解Megatron-DeepSpeed之模型并行与数据并行(中)06
七月在线实验室
10
《拆掉思维里的墙》:让你彻底走出恐惧的两张方法
梭罗在《瓦尔登湖》中说道:“无论你的生活多么艰难,请正视它,好好地活下去;别逃避它,也别咒骂它。它并没有你那么糟糕。”很多我们恐惧的事情,一旦我们真正去正视它的时候,其实它并没有那么可怕。恐惧其实就是一个欺软怕硬的货色,遇强它就弱,遇弱它就强。遇到问题,自己强势一点,相信一定可以解决它,那么心中那股
胖琪的升级之路
23
以环境之“优”谋发展之“势”
好的营商环境是生产力、竞争力,更是吸引力。近年来,我县始终坚持“项目为王、环境是金”工作导向,践行101%服务理念,大力优化营商环境,厚植高质量发展沃土,为县域经济发展提供强大支撑。 紧盯重大项目,推动企业投产增效 江苏伟复能源有限公司主要生产铅酸动力蓄电池,产品直供
盱眙老妹
0
APP保持屏幕常亮的几种方法
和你一起终身学习,这里是程序员Android经典好文推荐,通过阅读本文,您将收获以下知识点:一、申请WAKE_LOCK 权限二、Activity 中设置FLAG_KEEP_SCREEN_ON FLAG一、申请WAKE_LOCK 权限在AndroidMainfest.xml 中申请 WAKE_LOCK
程序员Android
10
炫技Groovy!SpringBoot中的动态编程实战
来源:juejin.cn/post/7139877924676567048👉 欢迎加入小哈的星球 ,你将获得: 专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡 / 赠书福利全栈前后端分离博客项目 2.0 版本完结啦, 演示链接
小哈学Java
10