使用类和实例的Ruby方法

时间:2015-05-06 00:09:29

标签: ruby

我正在尝试编写一个返回"Title was written by author"的方法,其中titleauthor是变量。我想我很接近,但我不确定此时要添加什么。

class Book
  def set_title_and_author=(title, author)
    @title = title
    @author = author
  end
  def set_title_and_author
    "#{@title} was written by #{@author}"
  end
end

3 个答案:

答案 0 :(得分:2)

你的问题是以=结尾的方法是不寻常的,因为它们必须有一个参数,而你传递的是两个(titleauthor)。 (另外,Ruby允许您在=之前插入空格;例如,set_title_and_author = arg。)

我可以建议你解决这个问题的四种方法:

  • 使参数成为数组[title, author](即单个值);
  • 将方法名称更改为set_title_and_author(并重命名getter);
  • 将方法set_title_and_author=替换为两个setter title=author=,您可以通过执行方法attr_writer :title, :author或者明确地写出来或让Ruby为您执行此操作attr_accessor :title, :author;或
  • 使用initialize方法作为设置器。

第一种方式

class Book
  def title_and_author=(arr)
    @title, @author = arr
  end
  def title_and_author
    "#{@title} was written by #{@author}"
  end
end

b = Book.new
  #=> #<Book:0x007f91e414eb78> 
b.title_and_author=(["Moby Dick", "Herman Melville"])
  #=> ["Moby Dick", "Herman Melville"] 
b.title_and_author
  #=> "Moby Dick was written by Herman Melville" 

请注意,我通过删除set_重命名了您的方法。在第一种情况下不需要set,在第二种情况下会误导,get更合适,但不需要。

第二种方式

class Book
  def set_title_and_author(title, author)
    @title = title
    @author = author
  end
  def title_and_author
    "#{@title} was written by #{@author}"
  end
end
b = Book.new
b.set_title_and_author("Moby Dick", "Herman Melville")
b.title_and_author
  #=> "Moby Dick was written by Herman Melville" 

请注意,我已将第一个方法的名称更改回set_title_and_author。它不能与getter方法同名,如果最后没有=,则需要修改名称以建议它的作用。

我更喜欢“第二种方式”(使参数成为数组)。

第三种方式

class Book
  attr_writer :title, :author
  def title_and_author
    "#{@title} was written by #{@author}"
  end
end
b = Book.new
b.title  = "Moby Dick"
b.author = "Herman Melville"
b.title_and_author
  #=> "Moby Dick was written by Herman Melville"  

第四种方式

class Book
  def initialize(title, author)
    @title = title
    @author = author
  end
  def title_and_author
    "#{@title} was written by #{@author}"
  end
end
b = Book.new("Moby Dick", "Herman Melville")
b.title_and_author
  #=> "Moby Dick was written by Herman Melville" 

这是设置实例变量的一种非常常见的方式。

答案 1 :(得分:1)

按照@ orde的回答,我还会使用精彩的#attr_accessor方法为titleauthor自动创建setter和getter。

class Book
  # create the setter and getter methods
  attr_accessor :title, :author

  # create an optional initializer
  def initialize(title = nil, author = nil)
    @title = title
    @author = author
  end

  def print_title_and_author
    puts "#{@title} was written by #{@author}"
  end
end

book = Book.new("Blood Meridian", "Cormac McCarthy")
book.print_title_and_author
# => Blood Meridian was written by Cormac McCarthy

book.title = "Blue moon"
book.print_title_and_author
# => Blue moon was written by Cormac McCarthy

首选为不同的属性创建不同的setter和getter。

您还可以创建链式设置器,这现在正成为一种趋势,因此您可以使用一行代码设置许多属性。您可以在执行任务(设置属性)后返回self来执行此操作:

# Reopen the class to add methods,
# the old code is still being used!
class Book
  def set_title title
    @title = title
    self
  end
  def set_author author
    @author = author
    self
  end
  def to_s
    "#{@title} was written by #{@author}"
  end
end

#chain set attributes
book.set_title('My New Title').set_author('Me')
#print the output - notice the #to_s is implied
puts book
# => My New Title was written by Me

您不需要初始值设定项,但请注意,如果未设置属性,当前的#print_title_and_author#to_s方法会产生有趣的输出。

我们可以使用if语句更改它(实际上,我将使用unless)。再次打开课程并重新定义这些方法:

# Reopen the class to add methods,
# the old code is still being used!
class Book

  def to_s
    return "author or title missing!" unless @author && @title
    "#{@title} was written by #{@author}"
  end

  def print_title_and_author
    puts self.to_s #DRY code - do not repeat yourself.
  end

end

new_book = Book.new
puts new_book
# => author or title missing!

我认为这样更好。

祝你好运,欢迎来到Ruby!

答案 2 :(得分:0)

您应该使用initialize方法设置对象的初始状态,而不是使用setter方法来分配标题和作者:

class Book
  def initialize(title, author)
    @title = title
    @author = author
  end

  def print_title_and_author
    puts "#{@title} was written by #{@author}"
  end
end

book = Book.new("Blood Meridian", "Cormac McCarthy")
book.print_title_and_author
#=> Blood Meridian was written by Cormac McCarthy