我是红宝石的新手。
我没有得到的是,如果某些模式在我的代码中重复出现,我应该做些什么来减去那部分并保存问题。
,例如,现在看来是这样的:
class Book
def initialize(title, author)
@title = title
@author = author
end
def info
puts [@title, @author]
end
end
我希望代码看起来像:
class Book(title, author)
def info
puts [title, author]
end
end
我可以提出什么理由:
每次创建对象时都会调用initialize。所以,如果每次创建一个对象时我想做的事情,初始化是正式的方式。
initialize表示构造函数将采用多少个参数。没有它,它将需要0。
但对我来说,它看起来仍然没用。有可能我可以改变语法看起来像第二个,而不是每次创建一个类时都要进行初始化,如果我没有什么特别的东西可以在构造时执行吗?
答案 0 :(得分:4)
Struct
确实存在:
Book = Struct.new(:title, :author)
book = Book.new('Fear & Trembling', 'Søren Kierkegaard')
book.title #=> "Fear & Trembling"
book.author #=> "Søren Kierkegaard"
您可以将新方法添加到Book中,而不是将其传递给块:
Book = Struct.new(:title, :author) do
def info
[title, author]
end
end
book = Book.new('Zur Genealogie der Moral', 'Friedrich Nietzsche')
book.info #=> ["Zur Genealogie der Moral", "Friedrich Nietzsche"]
或通过子类化:
class Book < Struct.new(:title, :author)
def info
[title, author]
end
end
有关使用属性构建类的更多功能,请查看Virtus。
答案 1 :(得分:2)
类不是方法,因此它不接受参数。初始化的目的是在新创建对象时执行任何类型的前期工作。例如:
book = Book.new('A Tale of Two Cities', 'Charles Dickens')
#=> #<Book:0x007f9f5a8933d8 @title="A Tale of Two Cities", @author="Charles Dickens">
如果您向该类添加attr_accessor
,您可以访问每个实例变量,如下所示:
class Book
attr_accessor :title, :author
def initialize(title, author)
@title = title
@author = author
end
def info
puts [@title, @author]
end
end
book.title
#=> "A Tale of Two Cities"
book.author
#=> "Charles Dickens"
答案 2 :(得分:1)
免责声明:如果您只想要一个简单的属性包装(即没有花哨的方法),可以考虑使用类似OpenStruct或Hash的东西。
话虽如此,这里有一些元编程用于创建你所描述的简单类。
def simple_class *attrs
klass = Class.new
klass.class_eval do
define_method('initialize') do |*args|
if args.size != attrs.size
raise ArgumentError.new("wrong number of arguments (#{args.size} for #{attrs.size})")
end
attrs.zip(args).each do |att, arg|
instance_variable_set("@#{att}", arg)
end
end
define_method('info') do
attrs.map { |att| instance_variable_get("@#{att}") }
end
end
klass
end
Book = simple_class(:title, :author)
b = Book.new("A BOOK", "ME")
puts b.info
答案 3 :(得分:0)
不,你不能改变固有的Ruby语言来做你所建议的。但是,由于语言非常灵活,您可以定义一种基本上与您描述的行为相似的方法,例如。
def new_class(class_name, *class_args)
# insert Ruby metaprogramming code here
end
new_class(:Book, :title, :author) do
def info
puts [title, author]
end
end
end