红宝石的反射? [英] Reflection in ruby?

查看:51
本文介绍了红宝石的反射?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很好奇这是如何工作的.例如,如果我创建一个基于工厂模式的类,您可以在其中注册"类以供以后使用,然后执行类似

的操作

FactoryClass.register('YourClassName', [param, param, ...]);FactoryClass.create('your_class_name').call_method_from_this_object

其中 'class_name' 是映射到值的哈希键:ClassName

是否有类似 php 反射 之类的东西,我可以在其中创建一个实例基于字符串名称的类并传入参数?(在 php 中,参数将是一个数组,然后 php 知道如何处理)

因此,如果我们以现实世界为例:

class Fooattr_reader : 东西定义初始化(输入)@something = 输入结尾def get_something返回@something结尾结尾# 在工厂类中,foo 被放入一个散列中:{'foo' =>'福'}# 这一步可能不需要??FactoryClass.create('Foo', ['hello'])# 在你的代码中的一些地方:FactoryClass.create('foo').get_something # =>你好

这可以在 ruby​​ 中实现吗?我知道一切本质上都是一个对象,但我还没有看到任何关于从这样的字符串名称创建类实例以及传入对象的 API 或文档.

至于上面的哈希,现在想想我可能不得不做这样的事情:

{'foo' =>{'类' =>'Foo', 'params' =>[参数,参数,...]}}

这样,当您在 FactoryClass 上调用 .create 时,它会知道,好的,我可以使用关联的参数实例化 Foo.

如果我离基地很远,请随时教育我.

解决方案

这里有一个不使用 eval 的答案.

PHP 的 Reflection 在 Ruby 中称为 Metaprogramming,但它们有很大的不同.Ruby 中的所有内容都是开放的并且可以访问.

考虑以下代码:

class Fooattr_reader : 东西定义初始化(输入)@something = 输入结尾def get_something返回@something结尾结尾@注册 = { }def register(reference_name, class_name, params=[])@registered[reference_name] = { class_name: class_name, params: [params].flatten }结尾定义创建(reference_name)h = @registered[reference_name]Object.const_get(h[:class_name]).new(*(h[:params]))结尾register('foo', 'Foo', ['something'])puts create('foo').get_something

您可以使用 Object#const_get 从字符串中获取对象.Object.const_get('Foo') 会给你对象 Foo.

但是,您不需要将类名作为字符串发送.您也可以将类名作为对象传递并直接使用.

class Fooattr_reader : 东西定义初始化(输入)@something = 输入结尾def get_something返回@something结尾结尾@注册 = { }def register(reference_name, class_name, params=[])@registered[reference_name] = { class_name: class_name, params: [params].flatten }结尾定义创建(reference_name)h = @registered[reference_name]h[:class_name].new(*(h[:params]))结尾register('foo', Foo, ['别的东西'])puts create('foo').get_something

I am curious how this works. For example if I create a factory pattern based class where you can "register" classes for later use and then do something like

FactoryClass.register('YourClassName', [param, param, ...]);
FactoryClass.create('your_class_name').call_method_from_this_object

where 'class_name' is a key in a hash that maps to value: ClassName

is there anything like php reflection, where I can create an instance of a class based on a string name and pass in the arguments in? (in php the arguments would be an array of them that php then knows how what to do with)

So if we take a real world example:

class Foo
  attr_reader :something

  def initialize(input)
    @something = input
  end

  def get_something
    return @something
  end
end

# In the factory class, foo is then placed in a hash: {'foo' => 'Foo'}
# This step might not be required??
FactoryClass.create('Foo', ['hello'])

# Some where in your code:
FactoryClass.create('foo').get_something # => hello

Is this possible to do in ruby? I know everything is essentially an object, but I haven't seen any API or docs on creating class instances from string names like this and also passing in objects.

As for the hash above, thinking about it now I would probably have to do something like:

{'foo' => {'class' => 'Foo', 'params' => [param, param, ...]}}

This way when you call .create on the FactoryClass it would know, ok I can instantiate Foo with the associated params.

If I am way off base, please feel free to educate me.

解决方案

Here is an answer that doesn't use eval.

PHP's Reflection is called Metaprogramming in Ruby, but they are quite different. Everything in Ruby is open and could be accessed.

Consider the following code:

class Foo
  attr_reader :something

  def initialize(input)
    @something = input
  end

  def get_something
    return @something
  end
end

@registered = { }
def register(reference_name, class_name, params=[])
  @registered[reference_name] = { class_name: class_name, params: [params].flatten }
end

def create(reference_name)
  h = @registered[reference_name]
  Object.const_get(h[:class_name]).new(*(h[:params]))
end

register('foo', 'Foo', ['something'])
puts create('foo').get_something

You can use Object#const_get to get objects from strings. Object.const_get('Foo') will give you the object Foo.

However, you don't need to send class name as string. You can also pass around the class name as object and use that directly.

class Foo
  attr_reader :something

  def initialize(input)
    @something = input
  end

  def get_something
    return @something
  end
end

@registered = { }
def register(reference_name, class_name, params=[])
  @registered[reference_name] = { class_name: class_name, params: [params].flatten }
end

def create(reference_name)
  h = @registered[reference_name]
  h[:class_name].new(*(h[:params]))
end

register('foo', Foo, ['something else'])
puts create('foo').get_something

这篇关于红宝石的反射?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆