简体   繁体   中英

Returning objects from Ruby Classes

I'm convinced I've had this working before!

I have the following class. The title string is created within the class the fname and lname strings are passed in as parameters. However, I can't seem to ever get the @title object to return anything other than nil.

What am I doing wrong here?

class Person
  attr_accessor :fname, :lname, :title

  def initialize(fname, lname)
    @fname = fname
    @lname = lname
    @title = title
  end

  def string1
    @lname + ", " + @fname
  end

  @title = "Director"

  def string2
    @title
  end

end

p = Person.new("Yukihiro", "Matsumoto")

p p.string1
p p.string2

Within the context of your class, @title refers to the class instance variable. Within the context of an instance method, @title refers to an instance variable. You're confusing these two.

What you need instead is a lazy initializer if you have some kind of default that you need applied:

def title
  @title ||= "Director"
end

Or better, to populate it in the first place. One way to fix this is to augment your initialize method:

def initialize(fname, lname, title = nil)
  @fname = fname
  @lname = lname
  @title = title || "Director"
end

You're not passing title to the constructor. You need to have something along the lines of

def initialize(fname, lname, title)
    @fname = fname
    @lname = lname
    @title = title
end

and call it with

p = Person.new("Yukihiro", "Matsumoto", "sensei")

The line @title = "Director" is executed during the class definition, which sets the variable on the class Person itself, rather than during the construction of an instance of the class, which is why the instance variable @title is not being set to "Director" in the new object you create with Person.new .

In fact, here's how to show that this is what's happening. Adding this method

class Person
    def self.string3
        @title
    end
end

adds a class method to Person to get the class's instance variable that was set during the class definition:

>> p Person.string3
"Director"

The following code:

class Person
  attr_accessor :fname, :lname

  def initialize(fname, lname)
    @fname = fname
    @lname = lname
  end

  def string1
    @lname + ", " + @fname
  end

  def title
    @@title
  end

  @@title = "Director"

  def string2
    @@title
  end

end

p = Person.new("Yukihiro", "Matsumoto")

p p.string1
p p.string2

gives the following output when run with Ruby 1.9.3:

"Matsumoto, Yukihiro"
"Director"

I've assumed that you want to keep the title the same for all the objects you create. If not, then iamnotmaynard 's answer is what you're after.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM