2013-03-07 110 views
4

我一直在研究学习一种新的动态脚本语言,用于Web开发,并且在对Python和Ruby感到痛苦之后,我真的很喜欢这两种,我决定选择Ruby(它几乎归结为一个投掷硬币,事实上在英国有比Python/Django更多的RoR工作)。我的问题是关于Ruby中的范围。我是否必须在方法中声明一个类属性才能从其他方法访问它?Ruby变量范围

举例来说,我不能做

class Notes 
    @notes = ["Pick up some milk"] 

    def print_notes 
    puts @notes 
    end 
end 

看来我得声明我要在构造函数中使用属性?这个例子的作品:

class Notes 
    def initialize 
    @notes = ["Pick up some milk"] 
    end 

    def print_notes 
    puts @notes 
    end 
end 

这是正确的吗?我注意到了用@@替代@作为前缀的例子,但是为了我的理解,如果类有一个子类(比如Memo),那么在Notes中对以@@为前缀的属性所做的任何更改都会改变Memo中的值?

很抱歉,如果这是一个重复的问题,只是失去了noobie :)

回答

4

在声明@notes类中而不是在构造函数或实例方法,那么你正在@notes一个实例变量本类本身的实例。每个班级也都以Class的实例存在。

class Notes 
    @notes = ["Pick up some milk"] 

     def print_notes 
     puts @notes 
     end 
    end 
# => nil 
Notes.instance_variable_get(:"@notes") 
# => ["Pick up some milk"] 

所以答案是肯定的,你需要在构造函数或其他实例方法中声明实例变量。我想你会喜欢这样做:

class Notes 
    def notes 
    @notes ||= [] 
    end 

    def print_notes 
    puts @notes 
    end 
end 

note = Notes.new 
note.notes << "Pick up some milk" 
note.notes 
# => ["Pick up some milk"] 

另外:

只要避免类变量如@@notes。改用类实例变量(这是你不知情的做法)。

这样做:

class Notes 
    def self.notes 
    @notes ||= [] 
    end 
end 

不是这个:

class Notes 
    def notes 
    @@notes ||= [] 
    end 
end 
当你想要一个类变量

。后者会导致你在路上遇到问题。 (但我认为这是用于不同对话的东西。)

+0

这个(你写的最后一段代码片段)和使用'attr_reader','attr_writer'和'attr_accessor'相同吗?如果是这样,那是做事情的首选方式吗? – Iain 2013-03-07 12:27:46

+0

@Iain附加信息之前的最后一个片段?是和不是。是的,它与'attr_reader'相同。不,因为它定义了一个默认值,而不是'nil',我之所以这样做是因为它是一个数组,否则第一次设置它时,你必须使用'note.notes = [“whatever”]''。因为默认值是一个数组,所以_in practice_和attr_accessor非常相似,因为你可以操作数值(数组),尽管你不能用'='替换数组。 – iain 2013-03-07 12:38:49

+0

@Iain既然您已经可以编程了,那么我建议您阅读“Ruby中的元编程”以获得广泛的范围及其如何影响事物的讨论,但互联网和其他书籍上有很多资源(也许其他人会提出一些)。 – iain 2013-03-07 12:42:23