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

时间:2016-06-13 03:14:50

标签: ruby variables module instantiation

我有以下模块,其中包含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 Decade
  include Week

  def firstday
    puts Week::first_day
  end
end

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

z = Decade.new
z.weeks_in_month
z.weeks_in_year

z.firstday #Errors here

我得到的错误是:

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

我是Ruby的新手,我刚刚习惯了模块,所以任何帮助都会受到赞赏。

1 个答案:

答案 0 :(得分:0)

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

module Week
  FIRST_DAY = 'Sunday'
end

请注意,他们在ALL_CAPS中。任何以大写字母开头的东西都被视为常数。该类的小写名称被视为局部变量。

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

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

此处还有其他一些注意事项。首先,只要您在include上调用module,就可以获得本地加载的方法常量。第二件事是当你定义一个混合模块时,要小心你的名字以避免与目标类的潜在冲突。

由于您已将其混入,因此您不需要命名空间前缀,只需调用first_day即可。