Каков наиболее эффективный способ инициализации класса в Ruby с разными параметрами и значениями по умолчанию?
Я хотел бы иметь класс и некоторые атрибуты, которые вы можете установить во время инициализации или использовать свое значение по умолчанию.
class Fruit
attr_accessor :color, :type
def initialize(color, type)
@color=color ||= 'green'
@type=type ||='pear'
end
end
apple=Fruit.new(red, apple)
Ответы
Ответ 1
Типичный способ решения этой проблемы - с хешем, который имеет значение по умолчанию. Ruby имеет хороший синтаксис для передачи хэш-значений, если хэш является последним параметром метода.
class Fruit
attr_accessor :color, :type
def initialize(params = {})
@color = params.fetch(:color, 'green')
@type = params.fetch(:type, 'pear')
end
def to_s
"#{color} #{type}"
end
end
puts(Fruit.new) # prints: green pear
puts(Fruit.new(:color => 'red', :type => 'grape')) # prints: red grape
puts(Fruit.new(:type => 'pomegranate')) # prints: green pomegranate
Хороший обзор здесь: http://deepfall.blogspot.com/2008/08/named-parameters-in-ruby.html
Ответ 2
Так как Ruby 2.0 поддерживает именованные или ключевые параметры.
Вы можете использовать:
class Fruit
attr_reader :color, :type
def initialize(color: 'green', type: 'pear')
@color = color
@type = type
end
def to_s
"#{color} #{type}"
end
end
puts(Fruit.new) # prints: green pear
puts(Fruit.new(:color => 'red', :type => 'grape')) # prints: red grape
puts(Fruit.new(:type => 'pomegranate')) # prints: green pomegranate
Некоторые интересные заметки по этой теме:
Ответ 3
Брайан отвечает отлично, но я хотел бы предложить некоторые изменения, чтобы сделать его главным образом мета:
class Fruit
# Now this is the only thing you have to touch when adding defaults or properties
def set_defaults
@color ||= 'green'
@type ||= 'pear'
end
def initialize(params = {})
params.each { |key,value| instance_variable_set("@#{key}", value) }
set_defaults
instance_variables.each {|var| self.class.send(:attr_accessor, var.to_s.delete('@'))}
end
def to_s
instance_variables.inject("") {|vars, var| vars += "#{var}: #{instance_variable_get(var)}; "}
end
end
puts Fruit.new
puts Fruit.new :color => 'red', :type => 'grape'
puts Fruit.new :type => 'pomegranate'
puts Fruit.new :cost => 20.21
puts Fruit.new :foo => "bar"
f = Fruit.new :potato => "salad"
puts "f.cost.nil? #{f.cost.nil?}"
Какие выходы:
@color: green; @type: pear;
@color: red; @type: grape;
@color: green; @type: pomegranate;
@color: green; @type: pear; @cost: 20.21;
@color: green; @type: pear; @foo: bar;
f.cost.nil? true
Конечно, это не было бы идеальным решением для всего, но оно дает вам некоторые идеи о том, как сделать ваш код более динамичным.
Ответ 4
Я бы сделал это вот так:
class Fruit
attr_accessor :color, :type
def initialize(args={})
options = {:color => 'green', :type => 'pear'}.merge(args)
self.color = options[:color]
self.type = options[:type]
end
end
apple = Fruit.new(:color => 'red', :type => 'apple')
Таким образом, вам никогда не придется беспокоиться о недостающих аргументах или их заказе, и вы всегда будете иметь свои значения по умолчанию прямо там. .merge
, конечно, будет перезаписывать значения по умолчанию, если они присутствуют.
Ответ 5
Более простой способ:
class Fruit
attr_accessor :color, :type
def initialize(color = 'green', type = 'pear')
@color = color
@type = type
end
def to_s
"#{color} #{type}"
end
end
puts Fruit.new # prints: green pear
puts Fruit.new('red','apple') # prints: red apple
puts Fruit.new(nil,'pomegranate') # prints: green pomegranate
Ответ 6
Мне нравится vonconrad ответ, но будет иметь отдельный метод defaults
. Возможно, это неэффективно с точки зрения строк кода, но оно более интенсивно раскрывает и включает в себя меньше когнитивных накладных расходов, а меньшие когнитивные накладные расходы - это более эффективная работа над сайтом.
class Fruit
attr_accessor :color, :type
def initialize(args={})
options = defaults.merge(args)
@color = options.fetch(:color)
@type = options.fetch(:type)
end
def defaults
{
color: 'green',
type: 'pear'
}
end
end
apple = Fruit.new(:color => 'red', :type => 'apple')
Ответ 7
Еще более вкусный синтаксический сахар:
class Fruit
attr_accessor :color, :type
def initialize *args
@color, @type = args
end
end
pear = Fruit.new 'green', :pear