我正在Person.rb文件中创建一个新的Person类。当我在终端中使用ruby Person.rb时,它显示了一个NoMethodError:
Person.rb:12:in `<main>': undefined method `name=' for #<Person:0x00000001abb6d8> (NoMethodError)
Did you mean?  name这就是我写的代码:
class Person
    attr :name, :age, :gender
end
person = Person.new
person.name = "John"
person.age = 55
person.gender = "male"
puts(person.name, person.age, person.gender)有什么建议吗?
发布于 2019-05-18 18:11:36
如果您查看Module#attr,您将看到使用它有三个“重载”:
attr(name, …)→nilattr(name, true)→nilattr(name, false)→nil
然后,这些文件进一步解释了三者之间的区别:
第一种形式等价于
attr_reader。第二种形式等价于attr_accessor(name),但不推荐使用。最后一个表单等价于attr_reader(name),但不推荐使用。
因此,第一和第三种形式只产生读者,而不是作家。第二个表单生成一个读取器和一个编写器,但是它只接受一个name形式参数,您不能使用它来生成多个属性。
另外,表格二和表格三被否决,所有这三种形式都是非惯用的.
如果要使用非惯用的Module#attr修复代码,则需要这样做:
attr :name  , true
attr :age   , true
attr :gender, true您可以使用以下的方法来简化这一点
%i[name age gender].each do |attribute|
  attr attribute, true
end但是,正如文档中所提到的,这个表单是不可取的,正如我前面提到的,Module#attr是非惯用的。
惯用的方法是使用Module#attr_*族的方法,即Module#attr_reader、Module#attr_writer和Module#attr_accessor。
attr_accessor :name, :age, :gender注意,由于您的Person类实际上没有任何行为,所以您可以简单地用一个Struct替换它
Person = Struct.new(:name, :age, :gender)但是,请注意,访问器,特别是编写器,并不是好的面向对象设计。对象应该做些什么,它们应该有行为。您的Person对象没有任何行为,它们只包含数据。此外,一个对象在创建之后应该是有效的,但是您的Person对象在创建时是空的。最后,如果可能的话,对象应该是不可变的。
我们可以通过添加初始化程序来确保创建后的对象是有效的:
class Person
  attr_accessor :name, :age, :gender
  def initialize(name, age, gender)
    self.name, self.age, self.gender = name, age, gender
  end
end
person = Person.new('John', 55, 'male')注意:Struct将为我们创建一个初始化器。
如果要使对象不可变,则需要删除写入器(或使其为private)。不幸的是,Struct不会为我们这样做:
class Person
  attr_reader :name, :age, :gender
  private
  attr_writer :name, :age, :gender
  def initialize(name, age, gender)
    self.name, self.age, self.gender = name, age, gender
  end
end
person = Person.new('John', 55, 'male')现在,person在创建它之后已经完全初始化,并且它不能再被更改了。
发布于 2019-05-18 17:16:15
您需要做的一些修改:
请在您的红宝石类中使用attr_accessor :name, :age, :gender
然后试着:
 puts person.name
 puts person.age
 puts person.gender它应该对你有用..。
https://stackoverflow.com/questions/56201052
复制相似问题