2016-06-13 155 views
1

我有以下模块,其中有一个变量,其中包含一个字符串的假设年的第一天,1个方法输出一个字符串和另一种方法,还输出一个字符串:
模块和模块访问变量(Ruby语言)

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 

我现在实例十年和访问方法位于模块中使用数十年的对象。我的程序调用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和我只是习惯了模块,所以任何帮助将是赞赏。

+0

不要忘记用'{}'按钮或四个缩进空格来格式化代码。 – tadman

回答

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

还有一些其他的事情要注意这里。第一种方法是,只要您在module上调用include,那么您将获得本地加载的常量方​​法。第二件事是当你定义一个混合模块时,小心你的名字以避免与目标类的潜在冲突。

既然你把它混合在一起,你不需要命名空间前缀,只需调用first_day应该这样做。

+0

啊,我认为常量的大写字母只是一个约定,但我猜测它是实际的语法,因此这就是它没有编译的原因。我来自java背景,其中定义类定义和构造函数之间的值时会自动将其视为类变量,而不一定是局部变量,因此会与Ruby产生混淆。谢谢你的反馈。 – JmanxC