想要实现一个功能,就是Person中,正常情况下,Person的对象调用say_hi的时候只简单的输出“HI”,一旦通过start_trace方法之后,执行say_hi就输出一些跟踪信息.通过end_starce方法把跟踪信息去掉。具体代码如下:
class Person
TRACE_METHODS = [:say_hi, :say_goodbye]
def say_hi
puts "HI"
end
def say_goodbye
puts "GoodBye"
end
TRACE_METHODS.each do |method|
alias_method "#{method}_without_tracer", method
define_method :"#{method}_with_tracer" do
puts "trace start."
(self.send("#{method}_without_tracer"))
puts "trace over."
end
end
def start_trace
TRACE_METHODS.each do |method|
alias_method method, "#{method}_with_tracer"
end
end
def end_trace
TRACE_METHODS.each do |method|
alias_method method, "#{method}_without_tracer"
end
end
end
person = Person.new
person.say_hi
person.start_trace
person.say_hi
可是在执行的时候,报错如下
引用
undefined method `alias_method' for #<Person:0x283f534> (NoMethodError)
问题一: 我看文档alias_method不是Module类中的方法么,为什么在start_trace中没有办法调用?而在下面这段代码里面又可以正常调用:
TRACE_METHODS.each do |method|
alias_method "#{method}_without_tracer", method
define_method :"#{method}_with_tracer" do
puts "trace start."
(self.send("#{method}_without_tracer"))
puts "trace over."
end
end
把代码做一个修改成如下:
class Person
TRACE_METHODS = [:say_hi, :say_goodbye]
def say_hi
puts "HI"
end
def say_goodbye
puts "GoodBye"
end
TRACE_METHODS.each do |method|
alias_method "#{method}_without_tracer", method
define_method :"#{method}_with_tracer" do
puts "trace start."
(self.send("#{method}_without_tracer"))
puts "trace over."
end
end
end
class << Person
def start_trace
TRACE_METHODS.each do |method|
alias_method method, "#{method}_with_tracer"
end
end
def end_trace
TRACE_METHODS.each do |method|
alias_method method, "#{method}_without_tracer"
end
end
end
我把start_trace和end_trace方法拿出来,通过打开Person的类定义在插入,执行
person = Person.new
person.say_hi
Person.start_trace
person.say_goodbye
这次还是报错
引用
in `start_trace': uninitialized constant Class::TRACE_METHODS (NameError)
问题二:通过class << Person打开类定义空间与之前的不同么?为什么我已经定义了TRACE_METHODS,可是却访问不到?我试了把TRACE_METHODS改成全局变量的话可以正常运行。
最后把代码修改成如下:
class Person
TRACE_METHODS = [:say_hi, :say_goodbye]
def say_hi
puts "HI"
end
def say_goodbye
puts "GoodBye"
end
TRACE_METHODS.each do |method|
alias_method "#{method}_without_tracer", method
define_method :"#{method}_with_tracer" do
puts "trace start."
(self.send("#{method}_without_tracer"))
puts "trace over."
end
end
def self.start_trace
TRACE_METHODS.each do |method|
alias_method method, "#{method}_with_tracer"
end
end
def self.end_trace
TRACE_METHODS.each do |method|
alias_method method, "#{method}_without_tracer"
end
end
end
这回可以正常执行了
person = Person.new
person.say_hi
Person.start_trace
person.say_goodbye
执行结果如下:
引用
HI
trace start.
GoodBye
trace over.
上面我提到的那两个问题是怎么回事呢?有谁知道么,是我对语言的哪个地方没有理解好?
相关推荐
在这种方法中,我们只需要生成一个在[0, 1)区间内的均匀分布随机数,然后将其映射到概率分布函数上。如果分布函数是连续的,可以使用反变换方法:找到分布函数的逆函数,将随机数代入得到对应的样本值。在MATLAB中,...
- **is_subclass_of**、**is_a**:检查一个类是否是另一个类的子类或实例。 - **get_class_vars**、**get_object_vars**:获取类的变量或对象的公共属性。 - **get_class_methods**:获取类的所有方法。 - **trigger...
简单来说,如果你有一个已经定义的类,但出于某种原因你需要一个不同的名称,你可以使用`class_alias`函数来实现。它的原型是`bool class_alias(string $original, string $alias[, bool $autoload = TRUE])`,其中`...
这段代码首先让用户选择一个包含图标的文件,然后通过 `ExtractIcon` 函数提取所有图标,并使用 `DrawIcon` 函数将它们绘制到指定的图片框中。 #### 2. 图标填充 还可以利用 `DrawIcon` 函数填充屏幕,例如: ```...
以下是一个使用`Extern.Declare`的示例,调用Windows API中的`DeleteFile`函数来删除文件: ```vbnet Public Declare Function DeleteFile Lib "kernel32" Alias "DeleteFileA" (ByVal lpFileName As String) As ...
模块是Python中的一个重要概念,指的是一个包含定义和语句的Python文件。通过模块可以实现代码的复用,提高开发效率。 - **模块定义**: 在Python中,每一个`.py`文件就是一个模块。 - **模块执行**: 当第一次导入...
Spring提供别名功能,通过`<alias>`标签,可以在多个地方使用相同的对象,但使用不同的名称,例如`<alias name="person" alias="p"/>`。 【Spring容器中的对象】 Spring容器有多种创建对象的方法: 1. 无参构造...
为了使前后端通信更加规范,可以定义一个通用的返回结果格式,包含状态码、消息和数据等信息,以便前端根据返回结果做出相应的处理。 总结来说,Django实现登录短信验证涉及到的主要知识点有:Django集成Redis作为...
例如,假设有一个方法 `greet`,你可以为其创建别名 `hello`: ```ruby def greet puts "Hello!" end alias hello greet hello ``` 运行这段代码,将会输出 “Hello!”。 #### 总结 Ruby 的方法机制非常灵活,...
示例中的`Frigga::RPC::#{rpc_class}`引用的是一个类方法,而`define_method`和`alias`则在`Runner`类的实例上下文中使用,这意味着它们定义的是实例方法。 8. **Global Variables**: 使用`@@rpc_list`作为全局...
C# 6.0是微软推出的C#编程语言的一个重要版本,它引入了许多新特性,旨在提高开发效率和代码的可读性。本学习笔记将带你从零开始,逐步掌握C#的基础语法,并最终实现你的第一个项目设计。下面,我们将详细探讨C# 6.0...
在这个例子中,我们定义了一个QML组件,它有一个`fetchData`函数来发送GET请求到指定的API URL。当HTTP响应返回时,我们检查状态码,如果是200(表示成功),则打印接收到的数据;否则,打印错误信息。 对于更复杂...
如果基类的虚属性只有一个访问器,子类可以有一个或两个访问器。如果基类有get和set,子类也必须提供相同数量的访问器。 14. **abstract 和 virtual 一起使用**: abstract不能与virtual一起使用,因为abstract...
使用`using`关键字可以导入命名空间,但当一个命名空间内的类与当前作用域中的类名冲突时,可以通过`using alias = namespace.ClassName`来创建别名,优先使用别名。 2. **字符串(String)**: - `String array[]`...
Spring 2.0 是一个重要的 Java 框架,以其依赖注入和面向切面编程的能力而闻名。在Spring 2.0中,XML配置是配置Spring beans的主要方式,虽然在后续版本中引入了Java配置和注解配置等更简洁的方式,但在当时XML配置...
- **背景介绍**:`PlaySound` 是一个Windows API函数,用于播放指定的声音文件或内存中的声音数据。 - **类定义**: ```csharp public class Sound { private byte[] m_soundBytes; private string m_fileName;...
当用户通过浏览器访问一个CGI脚本时,Web服务器会读取这个脚本并将其传递给相应的解释器执行(如Perl解释器)。解释器执行脚本后,会将输出返回给Web服务器,Web服务器再将这些内容发送给用户的浏览器。这一过程允许...
- **`factory-bean`和`factory-method`属性**:通过指定一个Bean工厂和一个工厂方法来创建Bean。`factory-bean`属性指向一个已经定义的Bean,而`factory-method`则指明了工厂Bean中的哪个方法用于创建目标Bean。 -...