ruby方法是否应该修改类的实例方法?

时间:2011-08-04 02:38:40

标签: ruby oop

我正在Ruby中编写一个类,其中我有类的实例变量(即@person_summary_info@name@dob@favorite_food)。

要解析一段文本,我有一个公共方法,我从课外调用它(让我们称之为interpret)。

此方法调用一些私有类方法,例如get_name使用@person_summary_info来提取相应的信息(在这种情况下,是人的名字)。那些私人方法应该是:

a)使用实例@person_summary_info,或通过传递给他们的参数获取该信息(即get_name vs get_name(person_summary_info)

b)直接修改实例变量并不返回任何内容,或者在函数范围之外修改任何内容,并返回结果(即在get_name内,设置@name = 'John'return 'John' )?

这里的最佳做法是什么? 谢谢!

3 个答案:

答案 0 :(得分:1)

如果interpret()不是为了改变Person的特定实例的状态,那么考虑将方法命名为get_name_from_string(string),并可能使其成为静态,因为它对实例的状态没有任何作用。

如果希望interpret()更改Person的特定实例的状态,请考虑更改方法的名称,在其前面添加set并包含要设置的属性名称(set_name_from_string())。如果正在设置多个属性,那么可能是set_from_string()并包含一个代码注释,说明正在修改哪些实例变量。在内部,该方法可以调用get / set_name(),如下所述。

通常,getter / setter方法是公开的,应该非常简单,按照他们的名字建议:   - getName()返回实例变量@name   - setName(name)使用传入的值设置或覆盖实例变量@name并且不返回任何内容

在Java中,这是一种POJO,特别是Java Beans(不包括需要序列化的部分)它在几种不同语言中非常常见的编程实践,以便为实例变量提供公共setter / getter方法并且还有一个默认构造函数(一个不带参数的构造函数)和另一个构造函数,允许您在实例化Object时设置实例变量。

答案 1 :(得分:1)

直接从另一个班级使用@instance是一个很好的方法来解决问题。每个类都应该拥有自己的变量,并且应该直接分配/返回您想要处理或返回的任何内容..这意味着

@instance = my_class.get_name(person_summary_info)

而不是

my_class.get_name

试着想象一下如何使用@instance变量来测试代码,并有机会重用那段代码..

只是我的2c

答案 2 :(得分:1)

我在答案的底部将代码中最好的代表问题包含在代码中,但我想提出解决方案,因为我首先理解你的困境......

如果您的name属性可以公开访问,请执行此操作:

class Person
  attr_accessor :name

  def initialize(name)
    @name = name
  end

  def interpret(text_to_parse)
    # I have no idea what you are parsing in real life
    self.name = text_to_parse.split.last
  end
end

person = Person.new("Frederick")
puts person.name
# => "Frederick"
person.interpret("Please, call me Fred")
puts person.name
# => "Fred"

如果您的name属性不应(轻松)公开访问,请执行以下操作:(对于它的价值,几乎任何东西都可以通过Ruby中的某种方式访问​​。许多令人敬畏的事情之一!)

class Person
  def initialize(name)
    @name = name
  end

  def interpret(text_to_parse)
    # I have no idea what you are parsing in real life
    @name = text_to_parse.split.last
  end
end

person = Person.new("Frederick")
puts person.instance_variable_get("@name")
# => "Frederick"
person.interpret("Please, call me Fred")
puts person.instance_variable_get("@name")
# => "Fred"

而且,如上所述,这是我将您的问题最好地翻译成代码:

class Person
  def initialize
    @person_summary_info = { name: "foo" }
    @name = "bar"
    @dob = "baz"
    @favorite_food = "beer"
  end

  def interpret(text_to_parse)
    # Some kind of parsing?
    get_name_1
    # OR
    get_name_2(@person_summary_info)
    # OR
    get_name_3
    # OR
    @name = get_name_4
  end

  private
  def get_name_1
    @person_summary_info[:name]
  end

  def get_name_2(person_summary_info)
    person_summary_info[:name]
  end

  def get_name_3
    @name = 'John'
  end

  def get_name_4
    'John'
  end
end

希望你能明白为什么在评论中有一些关于你究竟要问的问题。如果没有别的,也许看到这将有助于您更清楚地形成您的问题,以便我们可以提供帮助!

最后,你应该避免在Ruby中编写自己的getter / setter,除非你需要将一些自定义代码挂钩到获取/设置过程 - 使用类级别attr_reader / attr_writer / attr_accessor宏为您创建它们。