在创建类时,我们应该在Ruby中添加attr_*方法吗



我在Ruby中创建类,没有任何attr_*方法,如attr_reader、attr_writer或attr_accessor。所以像这个

class DocumentIdentifier
def initialize( folder, name )
@folder = folder
@name = name
end
end

我的意思是,它可以像这样实例化,对

di = DocumentIdentifier.new(folder, 'image')

但我在一些ruby书中读到了一些代码,它们也向实例变量添加了attr_*,比如这个

class DocumentIdentifier
attr_reader :folder, :name
def initialize( folder, name )
@folder = folder
@name = name
end
end

我的问题是,我们应该在每个类定义中使用attr_*吗?原因是什么?

attr_reader将创建方法,这些方法将返回具有匹配名称的实例变量。

class Foo
attr_reader :bar
def initialize(bar)
@bar = bar
end
end

这意味着Foo的实例在内部和外部都将具有方法bar,该方法将使用实例变量@bar:的值进行响应

foo = Foo.new(1)
foo.bar
=> 1

依赖行为(方法(比依赖数据(直接实例变量(要好。

如果你通过attr_reader生成的方法访问数据,你就可以确保你的代码稍微多一些;经得起未来考验";通过将行为封装在同一个位置,因此最好始终通过它们访问所有实例变量

另一个有趣的方面是,您可以限制您的界面以满足您的需求。例如,如果您只在内部使用bar,就没有必要将其暴露给外部世界,因此:

class Foo
def initialize(bar)
@bar = bar
end
def zoo
bar
end

private
attr_reader :bar
end

将表现为:

foo = Foo.new(1)
foo.zoo
=> 1

但是:

foo.bar
NoMethodError (private method `bar' called for #<Foo:0x00005581544b83d8 @bar=1>)

如果这有道理,请告诉我,否则我会更新答案,提供更多细节。

attr_reader是一个"吸气剂方法";。换句话说,它允许我们声明数据属性将是可公开读取的。

在类的实例上保存数据属性时,默认情况下无法从类外部查看该数据。通过设置attr_reader,我们可以从任何地方访问该属性。

这里有一个使用";name";字段。

# without "attr_reader"
class DocumentIdentifier
def initialize(folder, name)
@folder = folder
@name = name
end
end
first_example = DocumentIdentifier.new(nil, 'test')
first_example.name

这将给出一个错误:

Traceback (most recent call last):
4: from /Users/ibell/.rvm/rubies/ruby-2.6.5/bin/irb:23:in `<main>'
3: from /Users/ibell/.rvm/rubies/ruby-2.6.5/bin/irb:23:in `load'
2: from /Users/ibell/.rvm/rubies/ruby-2.6.5/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>'
1: from (irb):9
NoMethodError (undefined method `name' for #<DocumentIdentifier:0x00007fe0160956e8 @folder=2, @name="l">)

现在,如果添加attr_accessor,同样的代码也会起作用。

class DocumentIdentifier
attr_reader :name
def initialize(folder, name)
@folder = folder
@name = name
end
end
second_example = DocumentIdentifier.new(nil, 'test')
second_example.name

这将给你字符串";测试";返回

正如我们需要读取数据一样,我们也可能想要写入它。attr_writer的工作原理与attr_reader类似,但它允许我们";设置";数据

class DocumentIdentifier
attr_writer :name
def initialize(folder, name)
@folder = folder
@name = name
end
end
second_example = DocumentIdentifier.new(nil, 'test')
second_example.name = 'we can change this text'
second_example.name

这将返回给您:'we can change this text'

最后,当您希望attr_readerattr_writer在同一属性上时,attr_accessor是一个快捷方式。

最新更新