开发者

Should a ruby method modify a class's instance method?

I am writing a class in Ruby where I have instance variables (i.e. @person_summary_info, @name, @dob, @favorite_food) for the class.

To parse a piece of text, I have a public method that I call from outside the class (let's call it interpret).

This method calls some private class methods such as get_name that use @person_summary_info to extract the respective piece of information (in this case, the name of the person). Should those private methods:

a) use the instance @person_summary_info, or get that information through 开发者_JS百科a parameter passed to them (i.e. get_name vs get_name(person_summary_info))

b) modify the instance variable directly and return nothing, or modify nothing outside the scope of the function, and return the result (i.e. inside get_name, set @name = 'John', or return 'John')?

What is the best practice here? Thanks!


I have included my best representation of your question in code at the bottom of my answer, but I'd like to present my solution as I understand your dilemma first...

Do this if your name attribute is meant to be publicly accessible:

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"

Do this if your name attribute should not be (easily) publicly accessible: (For what it's worth, pretty much anything can be accessed one way or another in Ruby. One of the many things that make it awesome!)

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"

And, as mentioned above, here's my best translation of your question into code:

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

Hopefully, you can see why there's some confusion in the comments about what you are asking exactly. If nothing else, maybe seeing this will help you to form your question more clearly so we can help!

Finally, you should avoid writing your own getters/setters in Ruby unless you need to hook in some custom code to the getting/setting processes -- use the class-level attr_reader/attr_writer/attr_accessor macros to create them for you.


If interpret() is not meant to change the state of a particular instance of Person, then consider naming the method something like get_name_from_string(string) and possibly making it static, since it doesnt do anything to the state of the instance.

If you want interpret() to change the state of a particular instance of Person, then consider changing the name of the method, prefixing it with set and include the attribute name being set (set_name_from_string()). If several attributes are being set, then perhaps set_from_string() and include a code comment stating what instance variables are being modified. Internally the method could call get/set_name() as described below.

Typically, getter/setter methods are public and should be quite simple, doing what their name suggests: - getName() returns the instance variable @name - setName(name) sets or overwrites the instance variable @name with the value passed in and returns nothing

In Java, this is a type of POJO, specifically Java Beans (excluding the part about needing to be serializable) Its very common programming practice in several different languages to have public setter/getter methods for the instance variables and to also have a default constructor (one that takes no arguments) and another constructor allowing you to set the instance variables upon instantiation of the Object.


using @instance directly from another class is a good way how to get into troubles. Each class should have it's own variables and anything you would like to process or return back should be assigned/returned directly.. that means that way

@instance = my_class.get_name(person_summary_info)

and not

my_class.get_name

Just try to imagine how to test that code using @instance variables and chance to reuse that piece of code..

just my 2c

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜