21、Ruby 中 method_missing 和 const_missing 的灵活运用

Ruby 中 method_missing 和 const_missing 的灵活运用

1. Ruby 钩子概述

在 Ruby 应用程序的生命周期中,有一些关键的时刻可以通过 Ruby 钩子来执行特定代码。常见的钩子有以下几种:
- inherited 方法 :当某个类添加了子类时,该方法会被调用,可用于跟踪类的子类。
- module included 方法 :当某个模块被包含在类中时,此方法会被调用,可用于在类包含模块时对类进行修改。
- at_exit 钩子 :在 Ruby 解释器退出之前,该钩子会被触发,例如 Test::Unit 会使用它来自动运行测试。

这些只是常见的钩子,实际上还有很多其他的 Ruby 钩子,能让代码了解程序的运行状态。

2. 处理缺失方法

想象一个场景,公司决定将 Document 类作为处理文本文档的标准。但一些经验不足的工程师反馈 Document 类“不工作”或“完全损坏”,可能是因为他们调用了不存在的方法,比如:

# Error: the method is content, not text!
doc = Document.new('Titanic', 'Cameron', 'Sail, crash, sink')
puts "The text is #{doc.text}"

当 Ruby 尝试调用一个不存在的方法时,它会先在类及其父类中查找该方法。如果找不到

你给出的结构体定义如下: ```c typedef struct _DMS_CMD_METHOD { const char *name; S32 (*handle)(JSON_OBJPTR req_obj, JSON_OBJPTR* rply_obj); } DMS_CMD_METHOD; #define DMS_CMD_METHOD_DESC(method_name, method_handle) \ {.name = method_name, .handle = method_handle} typedef struct _DMS_CMD_OBJ_CMD { const char *name; const DMS_CMD_METHOD *methods; const U32 method_num; } DMS_CMD_OBJ_CMD; ``` 这段代码从语法上看是**合法的 C 语言结构体定义**,但你仍然在编译时遇到了如下错误: ``` error: storage class specified for parameter 'DMS_CMD_METHOD' error: expected ':', ',', ';', '}' or '__attribute__' before '*' token error: storage class specified for parameter 'DMS_CMD_OBJ_CMD' ``` --- ## ✅ 错误原因分析: 虽然你给出的代码是正确的,但出现这些错误通常意味着: ### 🔍 1. **头文件未被正确包含** - 在使用 `DMS_CMD_METHOD` `DMS_CMD_OBJ_CMD` 类型之前,**没有正确包含定义它们的头文件**。 - 或者头文件被错误地包含在 `extern "C"` 块中(如果是 C++ 混合编译)。 ### 🔍 2. **宏定义干扰** - `S32`、`U32`、`JSON_OBJPTR` 等类型未被正确定义。 - 如果这些宏未定义,编译器会将其视为非法类型,从而导致结构体定义失败。 ### 🔍 3. **重复定义或命名冲突** - 如果 `DMS_CMD_METHOD` 或 `_DMS_CMD_METHOD` 被多次定义或与其它头文件冲突,也可能导致解析失败。 --- ## ✅ 排查与修复建议: ### ✅ 1. 确保头文件被正确包含 在使用这些结构体之前,确保你包含了定义它们的头文件,例如: ```c #include "dms_tool.h" ``` 并在该头文件中确保有完整的结构体定义类型定义。 --- ### ✅ 2. 定义缺失的类型(如 `S32`, `U32`, `JSON_OBJPTR`) 确保以下类型已定义: ```c typedef signed int S32; typedef unsigned int U32; // 假设 JSON_OBJPTR 是一个句柄或结构体指针 typedef struct json_object JSON_OBJPTR; ``` 或者: ```c typedef void* JSON_OBJPTR; ``` > 如果这些类型未定义,编译器将无法解析结构体成员,从而报错。 --- ### ✅ 3. 使用 `#ifndef` 防止重复定义 确保头文件有保护宏: ```c #ifndef DMS_TOOL_H #define DMS_TOOL_H // 你的结构体定义宏在这里 #endif // DMS_TOOL_H ``` --- ### ✅ 4. 使用 `extern "C"` 包裹(如果在 C++ 中使用) 如果你在 C++ 文件中使用这些结构体,请确保头文件被 `extern "C"` 包裹: ```c #ifdef __cplusplus extern "C" { #endif // 结构体定义... #ifdef __cplusplus } #endif ``` --- ## ✅ 最终建议的完整 `dms_tool.h` 示例 ```c #ifndef DMS_TOOL_H #define DMS_TOOL_H #include <stdint.h> // 假设的类型定义(根据实际情况调整) typedef int32_t S32; typedef uint32_t U32; typedef void* JSON_OBJPTR; typedef struct _DMS_CMD_METHOD { const char *name; S32 (*handle)(JSON_OBJPTR req_obj, JSON_OBJPTR* rply_obj); } DMS_CMD_METHOD; #define DMS_CMD_METHOD_DESC(method_name, method_handle) \ {.name = method_name, .handle = method_handle} typedef struct _DMS_CMD_OBJ_CMD { const char *name; const DMS_CMD_METHOD *methods; const U32 method_num; } DMS_CMD_OBJ_CMD; #endif // DMS_TOOL_H ``` --- ## ✅ 总结常见错误点: | 错误信息 | 原因 | |----------|------| | `storage class specified for parameter 'DMS_CMD_METHOD'` | 类型未定义或结构体定义不完整 | | `expected ':', ',', ';', '}' or '__attribute__' before '*' token` | 编译器无法识别类型名 | | `S32` / `U32` / `JSON_OBJPTR` 未定义 | 宏或类型缺失导致结构体定义失败 | --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值