4

我的问题可能很简单,但我无法在任何地方找到答案。

创建类时,例如:

class Book
  @author = "blabla"
  @title = "blabla"
  @number_of_pages"

我想创建一种方法来打印出我的变量。当我尝试时,我遇到了一个问题:

def Print
  puts @author, @title, @number_of_pages
end

我什么也得不到。

当我尝试:

def Print
  puts "@author, @title, @number_of_pages"
end

我直截了当:“@author,@title,@number_of_pages”

如何使该Print方法打印出变量的值?

4

3 回答 3

9

您应该将变量初始化移动到initialize

class Book
  def initialize
    @author = "blabla"
    @title = "blabla"
    @number_of_pages = 42 # You had a typo here...
  end
end

在你的问题中,变量是类实例变量(如果你对它感到好奇,你可以谷歌,但它在这里并不真正相关)。

初始化为(普通)实例变量,Print()如果您只是想转储状态,则您的第一个版本可以工作——它将每个参数打印在自己的行上。

为了使您的第二个版本Print()工作,您需要将变量包装起来#{}以进行插值:

def print # It's better not to capitalize your method names
  puts "#{@author}, #{@title}, #{@number_of_pages}"
end
于 2012-08-16T10:19:43.720 回答
1

除了 Darshan 已经非常出色的答案之外,这里是您可以做到的最佳方式

class Book

  attr_accessor :author, :title, :number_of_pages 
  #so that you can easily read and change the values afterward

  def initialize author, title, number_of_pages = nil 
    #so that you don't really need to provide the number of pages
    @author = author
    @title = title
    @number_of_pages = number_of_pages
  end

  def print
    puts "#{@author}, #{@title}, #{@number_of_pages}" 
  end 
end 

my_book = Book.new("blabla", "blabla", 42)
my_book.title = "this is a better title"
my_book.print

#=>blabla, this is a better title, 42
于 2012-08-16T12:09:01.490 回答
1

我认为达​​山计算已经很好地解决了你的问题。但在这里,我想为您提供实现这一目标的替代方法。

我假设您想打印出类中的所有实例变量。方法instance_variables可以返回符号中所有 instance_variables 的数组。然后你可以迭代它们做任何你想做的事情。请注意:instance_variable_get 非常方便,但不是最佳实践。

class Book
  attr_reader :author, :title, :number_of_pages

  def initialize(author, title, number_of_pages)
    @author = author
    @title = title
    @number_of_pages = number_of_pages
  end

  def print_iv(&block)
    self.instance_variables.each do |iv|
      name = iv
      value = send(iv.to_s.gsub(/^@/, ''))
      # value = instance_variable_get(iv) # Not recommended, because instance_variable_get is really powerful, which doesn't actually need attr_reader
      block.call(name, value) if block_given?
    end
  end
end

rb = Book.new("Dave Thomas", "Programming Ruby - The Pragmatic Programmers' Guide", 864)

# rb.instance_variables #=> [:@author, :@title, :@number_of_pages]
rb.print_iv do |name, value|
  puts "#{name} = #{value}"
end
#=> @author = Dave Thomas
#=> @title = Programming Ruby - The Pragmatic Programmers' Guide
#=> @number_of_pages = 864

# You can also try instance_eval to run block in object context (current class set to that object)
# rb.instance_eval do
#   puts author
#   puts title
#   puts number_of_pages
# end
于 2012-08-16T14:35:24.627 回答