以前,我问一个聪明的方式,在给定的条件下执行的方法“ 红宝石一个聪明的方式,在条件执行功能 。”
这些解决方案和响应时间是伟大的,但是,在实施中,具有lambda表达式的哈希相当迅速变得难看。 于是我开始尝试。
下面的代码工作:
def a()
puts "hello world"
end
some_hash = { 0 => a() }
some_hash[0]
但是,如果我把这个包在一个类它停止工作:
class A
@a = { 0 => a()}
def a()
puts "hello world"
end
def b()
@a[0]
end
end
d = A.new()
d.b()
我不明白为什么它应该停止工作,任何人都可以建议如何使它工作吗?
该代码不起作用。 它执行a
在它被添加到该散列的时间,而不是当它从散列检索(尝试在IRB)。
因为没有它不会在班上做a
在类中定义的方法(您最终定义方法a
实例上。
实际上尝试使用类似的lambda表达式
{0 => lambda { puts "hello world" }}
代替
首先,你是不是把一个拉姆达的哈希值。 你把调用的结果, a()
在当前的背景下。
鉴于这一信息,考虑一下在你的类代码单元。 一个类定义的上下文是类。 所以,你定义一个实例方法调用的a
,而一个类实例变量分配到包含调用的结果哈希a
在目前情况下。 当前上下文是A类和A类没有一个类的方法称为a
,所以你试图把一个不存在的方法的结果出现。 然后在实例方法b
,您尝试访问称为实例变量@a
-但没有一个。 该@a
在类上下文中定义属于类本身,而不是任何特定实例。
所以首先,如果你想有一个拉姆达,你需要做一个拉姆达。 其次,你需要明确的一类和类的实例之间的差别。
如果你想方法名称列表在一定条件下被调用,你可以做这样的:
class A
def self.conditions() { 0 => :a } end
def a
puts "Hello!"
end
def b(arg)
send self.class.conditions[arg]
end
end
这定义了条件哈希作为类的方法(因此很容易获得),和哈希仅包含方法的名字来称呼,而不是一个拉姆达或类似的东西。 所以,当你调用b(0)
它send
S本身包含在A.conditions [0]的消息,这是a
。
table = {
:a => 'test',
:b => 12,
:c => lambda { "Hallo" },
:d => def print(); "Hallo in test"; end
}
puts table[:a]
puts table[:b]
puts table[:c].call
puts table[:d].send( :print )
如果你真的只是想漂亮这样的事情了,为什么不换的,像这样一类的所有方法:
# a container to store all your methods you want to use a hash to access
class MethodHash
alias [] send
def one
puts "I'm one"
end
def two
puts "I'm two"
end
end
x = MethodHash.new
x[:one] # prints "I'm one"
x.two # prints "I'm one"
或者用你的例子:
# a general purpose object that transforms a hash into calls on methods of some given object
class DelegateHash
def initialize(target, method_hash)
@target = target
@method_hash = method_hash.dup
end
def [](k)
@target.send(@method_hash[k])
end
end
class A
def initialize
@a = DelegateHash.new(self, { 0 => :a })
end
def a()
puts "hello world"
end
def b()
@a[0]
end
end
x = A.new
x.a #=> prints "hello world"
x.b #=> prints "hello world"
您所做的另外一个基本的错误就是你初始化@a
任何实例方法之外的-只是定义的裸里面A
。 这是一个大的时间没有没有,因为它是行不通的。 请记住,在Ruby中,一切都是对象,包括类,和@
前缀是指无论对象是目前自实例变量。 内部的实例方法的定义, self
是类的一个实例。 但外界认为,仅仅是类定义中, self
是类对象-让你定义一个命名实例变量@a
的类对象A
,其中没有的情况下的A
能够得到直接。
红宝石确实有这种行为(类实例变量可以是非常方便的,如果你知道你在做什么)的一个原因,但是这是一种更先进的技术。
总之,只有在初始化实例变量initialize
方法。
那么,在你的类的第一行调用尚不存在的方法。 全班同学被加载但之后,因为这将是对类方法的调用和你只定义实例方法它甚至不会存在。
还请注意,{0 =>一()}将调用方法的(),不创建该方法,()的引用。 如果你想摆在那里的一个功能,没有得到评估,直到后来,你就必须使用某种类型的lambda。
我非常新的Ruby中使用回调,这是我如何用一个例子解释自己:
require 'logger'
log = Logger.new('/var/tmp/log.out')
def callit(severity, msg, myproc)
myproc.call(sev, msg)
end
lookup_severity = {}
lookup_severity['info'] = Proc.new { |x| log.info(x) }
lookup_severity['debug'] = Proc.new { |x| log.debug(x) }
logit = Proc.new { |x,y| lookup_sev[x].call(y) }
callit('info', "check4", logit)
callit('debug', "check5", logit)
A = - >(字符串= “无字符串传递”)做
把字符串
结束
some_hash = {0 =>一个}
some_hash [0] .CALL(的 “Hello World”)
some_hash [0] []