【问题标题】:Set instance variable in main after including module?包含模块后在main中设置实例变量?
【发布时间】:2016-12-05 00:42:13
【问题描述】:

这是我尝试设置实例变量的模块。我正在尝试初始化和 self.included,但是当我在最外层 (main) 范围内执行包含时,两者都不起作用:

module Asd
  def initialize
    @asd = 0
  end
  def self.included(base)
    @asd = 0
  end
  attr_reader :asd
end

将它包含在一个类中是可行的,我可以读取实例变量:

class Bsd
  include Asd
end
Bsd.new.asd
# => 0

但是在全球范围内这样做是行不通的:

include Asd
@asd
# => nil
asd 
# => nil

我知道人们经常会质疑将代码置于全球层面的动机。在这种情况下,我只想看看它是如何完成的。

【问题讨论】:

  • 我相信initialize 仅在您创建实例时运行。 Asd 是一个模块,你不能有一个模块的实例。然后,当您像以前那样在全局级别包含 Asd 时,您将不会运行 initialize
  • 至于asd方法...我真的不知道你为什么会得到NoMethodError
  • 我正在运行ruby 2.3.0p0,并调用include Asd,然后asd 给我nil,而不是NoMethodError。您可以使用Pry REPL 下的ls -pv 命令查看方法是否已定义。
  • self.included 方法内部的@asdinitialize 内部的不一样。不同的上下文。
  • EddeAlmeida & tewu 你是对的;我的错;已编辑问题

标签: ruby


【解决方案1】:

我希望这段代码能让它更清楚一点:

module Asd
  def initialize
    puts "# Initializing"
    @asd = "One @asd"
  end

  def self.included(base)
    puts "# Importing into #{base}"
    @asd = "Another @asd"
  end
  attr_reader :asd
end

class Bsd
  include Asd
  # => # Importing into Bsd
end

puts Bsd.new.asd
# =>
# Initializing
# One @asd

puts Asd.instance_variable_get(:@asd)
# => Another @asd

include Asd
# => # Importing into Object

puts self.asd.inspect # Method is defined for main, @asd hasn't been initialized because main was instantiated before the script was launched
# => nil

puts Object.new.asd
# =>
# Initializing
# One @asd

基本上,您的代码对于main 来说为时已晚。它在脚本启动之前已经被初始化,所以initialize内的代码将不再为main启动。

【讨论】:

    【解决方案2】:

    @EricDuminil 解释了为什么您的方法不起作用。以下是如何使它在这种情况下工作:直接设置实例变量,无需初始化器。

    module Asd
      def self.extended(base)
        base.instance_variable_set(:@asd, "Another @asd")
      end
    
      attr_reader :asd
    end
    
    @asd # => nil # !> instance variable @asd not initialized
    
    extend Asd # extend, not include.
    
    @asd # => "Another @asd"
    asd # => "Another @asd"
    

    【讨论】:

    • 啊哈,我正在为我的答案的第二部分写这个。不再需要它了!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-22
    • 2013-05-17
    • 2015-09-11
    • 1970-01-01
    • 2017-03-27
    • 2011-10-03
    • 1970-01-01
    相关资源
    最近更新 更多