我正在尝试编写一个返回"Title was written by author"
的方法,其中title
和author
是变量。我想我很接近,但我不确定此时要添加什么。
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
答案 0 :(得分:2)
你的问题是以=
结尾的方法是不寻常的,因为它们必须有一个参数,而你传递的是两个(title
和author
)。 (另外,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
方法为title
和author
自动创建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