模块和从模块访问变量(Ruby 语言)

Modules and Accessing Variables from Modules (Ruby Language)

我有以下模块,它有 1 个变量,其中包含假设年份的第一天的字符串,1 个输出字符串的方法和另一个也输出字符串的方法:

module Week
  first_day = "Sunday"

  def weeks_in_month
    puts "There are 4 weeks in a month"
  end

  def weeks_in_year
    puts "There are 52 weeks in a year"
  end
end

我现在有一个 class,他的唯一目的是打印出位于模块中的变量。(这仅用于测试目的)

class Decade
  include Week

  def firstday
    puts Week::first_day
  end
end

我现在实例化 Decade 并使用 Decades 对象访问模块中的方法。我的程序在调用 firstday 方法时遇到问题

z = Decade.new
z.weeks_in_month
z.weeks_in_year

z.firstday #Errors here

我得到的错误是:

undefined method `first_day' for Week:Module (NoMethodError)

我是 Ruby 的新手,刚刚开始使用模块,如有任何帮助,我们将不胜感激。

编写模块时,约定是这样声明常量:

module Week
  FIRST_DAY = 'Sunday'
end

请注意,它们在 ALL_CAPS 中。任何以大写字母开头的都被视为常量。这种小写名称被视为局部变量。

通常访问另一个模块的常量是一种不好的形式,它限制了您重构这些常量存储方式的能力。而是定义一个 public 访问器方法:

module Week
  def first_day
    FIRST_DAY
  end
end

现在您可以从外部调用它了:

Week.first_day

请注意,您还可以更改其实施方式:

module Week
  DAYS = %w[
    Sunday
    Monday
    Tuesday
    ...
    Saturday
  ]

  def first_day
    DAYS.first
  end

  extend self # Makes methods callable like Week.first_day
end

好处是 first_day 方法做的事情完全一样,无需更改其他代码。这使得重构变得更加容易。想象一下,如果您必须追踪并将所有这些实例替换为 Week::FIRST_DAY.

这里还有一些需要注意的地方。首先是任何时候你在 module 上调用 include 然后你会得到本地加载的方法 常量。第二件事是当你定义一个混合模块时,注意你的名字以避免与目标发生潜在的冲突class.

既然你已经混合了它,你就不需要命名空间前缀,只需调用 first_day 就可以了。