【问题标题】:Not understanding Classes, Modules, and the class << self method不了解类、模块和类 << self 方法
【发布时间】:2012-04-11 13:34:36
【问题描述】:

我有以下代码:

class MyClass  
  module MyModule
    class << self

      attr_accessor :first_name

      def myfunction
        MyModule.first_name = "Nathan"
      end

    end
  end
end

当我像这样调用 myfunction 方法时,它工作正常:

> me = MyClass::MyModule.myfunction
=> "Nathan"
> me
=> "Nathan"

但如果我删除了class &lt;&lt; self 并在myfunction 上添加了self. 前缀,它就不起作用了。

例如:

class MyClass  
  module MyModule

    attr_accessor :first_name

    def self.myfunction
      MyModule.first_name = "Nathan"
    end

  end
end


> me = MyClass::MyModule.myfunction
NoMethodError: undefined method `first_name=' for MyClass::MyModule:Module

我正在尝试理解class &lt;&lt; self 方法。我认为这是一种将self.前缀添加到其中的所有方法的方法,但如果这是真的,如果我删除它并手动为每个方法添加前缀self.,为什么它不起作用?

提前感谢您的帮助。

【问题讨论】:

标签: ruby-on-rails ruby


【解决方案1】:

为了更好地了解如何实现您想要的,请查看以下示例:

module PrintingModule

  def self.included(object)
    object.extend(ClassMethods)
  end

  module ClassMethods

    def class_method_of_class
      puts "I am class #{self.name}"
    end

  end

  def instance_method_of_class
    puts "My name is:  #{@name}"
  end

  class << self
    def static_module_method
      puts "Printer version 1.0"
    end
  end
end

class SomeObject
  include PrintingModule
  def initialize(name)
    @name = name
  end
end

object = SomeObject.new("Something")
object.instance_method_of_class
SomeObject.class_method_of_class
PrintingModule.static_module_method

我希望现在更清楚,注意这只是一种可能的方式(还有其他方式)

更新: 我会尝试更具体。当您在模块上定义实例/单例方法时,您真正要做的是定义将包含该模块的类的实例方法,另一方面,在模块上定义的类方法将成为该模块的类方法。第二个想法是 attr_accessor 为给定参数的 getter 和 setter 创建实例方法。

现在回答您问题的一部分,在第一个示例中,您将在模块的类上创建 3 个类方法。在第二个中,您正在创建 1 个类方法,您正在尝试访问另一个类方法(setter),但是您的 getter 和 setter 被定义为实例方法 = 它们将成为包含您的模块的类方法的实例,您无法以这种方式找到它们=您无法访问您的 getter 和 setter。 至于对自我的解释,我不是那么熟练,但据我所知,当你使用“class

text = "something"
class << text
  def say_hi
    puts "Hi!"
  end
end

text.say_hi

当您创建类的实例(该示例中为字符串)时,该实例将获得它自己的唯一匿名类,该类是该类的子类。在示例中,您在 String 类的匿名子类的特征类上定义了实例方法。因此,您可以在文本对象上使用方法“say_hi”,但不能在 String 类上使用。所以“class

另一方面,单独的“self”仅代表当前上下文中的一个对象,这在某些情况下(例如您的情况)意味着相同。至于 self.included 方法,它只是一个回调方法,当模块包含在具有表示对象的参数的类中时调用(这里是类 SomeObject)。

我希望我至少回答了您的部分问题。 更多信息在这里: Difference between 'self.method_name' and 'class << self' in Ruby

【讨论】:

  • 我知道你是如何使用 mixins 的,除了上面的 def self.included(object)... 之外,大部分都是有意义的。但问题是,我并不像我试图理解行为那样渴望实现任何目标。我不确定您的示例解释了为什么 class &lt;&lt; self 与混合模块一起使用,但 .self 前缀在尝试访​​问类方法时却没有。实际上,在我的示例中,我对实例方法 :first_name 如何在类调用中可用感到困惑。
  • 我已经更新了我的答案,我希望它至少能回答你的部分问题。祝你有美好的一天。
【解决方案2】:

这是因为您的attr_accessor :first_name 也被class &lt;&lt; self 包裹。

要按照您建议的方式进行操作,您可以像这样使用mattr_accessor

require 'active_support'

class MyClass  
  module MyModule

    mattr_accessor :first_name

    def self.myfunction
      MyModule.first_name = "Nathan"
    end

  end
end

【讨论】:

  • 所以这是依赖于 active_support 的特定于 Rails 的东西?我假设 mattr_accessor 是模块特定的 setter/getter 方法?
  • 没错。不管好坏,mattr_accessor 只能通过 Rails 访问。
  • 有很多东西有时我希望在常规 Ruby 中也可用,而不仅仅是 Rails 或 ActiveRecord。
猜你喜欢
  • 2011-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多