У меня есть два класса.Ruby Hash инициализировать путаницу
class Sky
attr_accessor :args
def initialize(args)
@args = args
puts 'Initializing sky'
end
end
class ShadowMask
attr_accessor :sky
def initialize(args)
args.each{|k, v| p "#{k}: #{v.to_s}"}
@sky = args.fetch(:sky, Sky.new({}))
end
end
ShadowMask
может быть создан либо по умолчанию Sky
:
sm_default = ShadowMask.new({})
# Initializing sky
# => #<ShadowMask:0x007fa215230eb0 @sky=#<Sky:0x007fa215230e60 @args={}>>
sm_default.sky
# => #<Sky:0x007fa215230e60 @args={}>
sm_default.sky.args
# => {}
или с Sky
, который был ранее создан:
skyobj = Sky.new("Sky Object")
# Initializing sky
# => #<Sky:0x007fa21481a020 @args="Sky Object">
sm = ShadowMask.new(:sky => skyobj)
# "sky: #<Sky:0x007fa21481a020>"
# Initializing sky
# => #<ShadowMask:0x007fa21521ae80 @sky=#<Sky:0x007fa21481a020 @args="Sky Object">>
В этом втором случае, экземпляр Sky
уже существует, и я не хочу видеть вывод Initializing sky
от Sky
инициализация.
Проблемы с моим фактическим кодом является то, что
puts 'Initializing sky'
является вызовом метода, который выполняет несколько вычислений для завершения инициализации и задать несколько атрибутов. И это повторяется без необходимости каждый раз, когда создается ShadowMask
.
Интересно, если я заменю
@sky = args.fetch(:sky, Sky.new({}))
с чем-то вроде
@sky = args.fetch(:sky, 'AnyString')
это работает хорошо, но я бы потерять возможность создания нового Sky
при необходимости.
Я не уверен, что проблема в синтаксисе или я делаю концептуальную ошибку.
Итак, с '||' 'args [: sky]' оценивается сначала, и только если это 'false' или' nil', тогда будет оцениваться 'Sky.new ({})'. Правильно? – Rojj
@Rojj: Да, это называется «оценка короткого замыкания», –