【问题标题】:When to use define_singleton_method v define_method何时使用 define_singleton_method v define_method
【发布时间】:2019-09-29 16:50:41
【问题描述】:

在对this question 用户的一个回答中,mu 太短了,解释说您不希望对象的行为在初始化时发生太大变化,这是有道理的,您应该能够通过阅读很好地推理对象它的定义和内省,但我想到了这个案例:

french_colors.yml

blue: blue
red: rouge
...

translations.rb

class Translations
  def initialize(language: "french")
    data = YAML.load_file("./translations/#{language}.yml")
    data.each do |k, v|
      define_method k do
        v
      end
    end

    print_french_colors
  end

  def print_french_colors
    puts red
    puts blue
  end
end

初始化时,上面的错误与 #=> NoMethodError: undefined method `define_method' for #<C:0x2efae80>

在这里,您根据从翻译公司收到的文件构建所有翻译行为,并希望它作为一个实例,还希望它基于语言文件是动态的(这只是一个示例)

在初始化中将翻译定义和设置为对象的属性,而不是在初始化中使用 define_method 像这个问题 OP 和我试图做的那样,会更有意义吗?或者是不是专门为处理这种情况而编写了define_singleton_method 方法?

How to use define_method inside initialize()

【问题讨论】:

    标签: ruby oop metaprogramming


    【解决方案1】:

    不清楚你的最终目标是什么。例如,如果语言不是法语,我不确定为什么会有print_french_colors 方法。看起来你基本上想读取一个 yaml 文件并使用它来设置一些预定义属性的值。

    为了实现这一点,我认为使用 instance_variable_set 而不是 define_method 更有意义。这是一个例子。

    法语.yml

    blue: blue
    red: rouge
    

    require "yaml"
    class Translations
      attr_reader :blue, :red 
      def initialize(language: "french")
        data = YAML.load_file("#{language}.yml")
        data.each do |k, v| 
            if respond_to?(k)
              instance_variable_set("@#{k}",v)    
            else 
              puts "#{k} is not defined"
            end
        end
    
        print_french_colors
      end
    
      def print_french_colors
        puts red
        puts blue
      end
    end
    
    t = Translations.new 
    t.print_french_colors
    

    【讨论】:

    • 这会强制您手动设置 attr_readers 以获得所需的实例变量,这违背了以编程方式定义方法/实例变量的目的。
    【解决方案2】:

    回到你的问题...替换下面的代码块

    define_method k do
      v
    end
    

    self.class.send(:define_method, k) do
      v
    end
    

    【讨论】:

    • 这不是“单例”一词在 Ruby 上下文中的使用方式。在 Ruby 中,单例方法是应用于对象的 Eigen 类(在 Ruby 中称为 Singleton 类)的方法。这些方法有效地附加到特定实例而不是对象类。这反映在标题中提到的两种方法中。 define_singleton_method 是在 abject 上创建单例方法的公共方法,而 define_method 是在类上创建方法的私有方法。
    • 单例设计模式仅与 Ruby 中的单例方法相关。特别是,两者之间的唯一关系是两者都使用标准英语(拉丁语)意义上的“singleton”一词。
    猜你喜欢
    • 2013-10-22
    • 1970-01-01
    • 1970-01-01
    • 2010-10-19
    • 1970-01-01
    • 2011-01-19
    • 1970-01-01
    • 2015-08-13
    • 2012-11-07
    相关资源
    最近更新 更多