我怎么叫这是一个散列值的方法?(How do I call a method that is a h

2019-06-24 17:34发布

以前,我问一个聪明的方式,在给定的条件下执行的方法“ 红宝石一个聪明的方式,在条件执行功能 。”

这些解决方案和响应时间是伟大的,但是,在实施中,具有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()

我不明白为什么它应该停止工作,任何人都可以建议如何使它工作吗?

Answer 1:

该代码不起作用。 它执行a在它被添加到该散列的时间,而不是当它从散列检索(尝试在IRB)。

因为没有它不会在班上做a在类中定义的方法(您最终定义方法a实例上。

实际上尝试使用类似的lambda表达式

{0 => lambda { puts "hello world" }} 

代替



Answer 2:

首先,你是不是把一个拉姆达的哈希值。 你把调用的结果, 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



Answer 3:

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 )


Answer 4:

如果你真的只是想漂亮这样的事情了,为什么不换的,像这样一类的所有方法:

# 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方法。



Answer 5:

那么,在你的类的第一行调用尚不存在的方法。 全班同学被加载但之后,因为这将是对类方法的调用和你只定义实例方法它甚至不会存在。

还请注意,{0 =>一()}将调用方法的(),不创建该方法,()的引用。 如果你想摆在那里的一个功能,没有得到评估,直到后来,你就必须使用某种类型的lambda。



Answer 6:

我非常新的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)


Answer 7:

A = - >(字符串= “无字符串传递”)做

把字符串

结束

some_hash = {0 =>一个}

some_hash [0] .CALL(的 “Hello World”)

some_hash [0] []



文章来源: How do I call a method that is a hash value?