Скажем, у меня есть родительский класс, инициализатор которого имеет аргумент со значением по умолчанию:
class Parent
attr_reader :foo
def initialize(foo: 123)
@foo = foo
end
end
Я хочу создать подкласс с тем же значением по умолчанию для foo
. Я могу сделать это, если повторю объявление:
class Child < Parent
attr_reader :bar
def initialize(foo: 123, bar: 456)
super(foo: foo)
@bar = bar
end
end
Однако это означает, что я должен написать 123
дважды. Если я попытаюсь избежать повторения этого, опустив его...
class Child < Parent
attr_reader :bar
def initialize(foo:, bar: 456)
super(foo: foo)
@bar = bar
end
end
-- теперь это означает, что ранее необязательный foo
по умолчанию теперь требуется для подкласса, и на самом деле я вообще не получаю никакой выгоды от значения по умолчанию.
Я подумал, что смогу установить по умолчанию nil
в подклассе --
class Child < Parent
attr_reader :bar
def initialize(foo: nil, bar: 456)
super(foo: foo)
@bar = bar
end
end
-- но нет; Child.new(bar:789).foo
теперь nil
, тогда как я хотел 123
.
Я тоже не могу полностью отказаться от аргумента...
class Child < Parent
attr_reader :bar
def initialize(bar: 456)
super(foo: foo)
@bar = bar
end
end
-- потому что тогда, если я попытаюсь указать это (Child.new(foo: 345, bar:789)
), я получу unknown keyword: foo (ArgumentError)
.
Есть ли способ фактически опустить аргумент вместо того, чтобы присвоить ему значение по умолчанию? И/или способ разрешить инициализатору принимать произвольные дополнительные именованные параметры и передавать их инициализатору суперкласса?
Обновление: я придумал следующий хак (по сути, вручную меняя свои собственные «параметры по умолчанию»), но я не очень доволен этим.
class Parent
attr_reader :foo
def initialize(foo: nil)
@foo = foo || 123 # faking 'default'-ness
end
end
class Child < Parent
attr_reader :bar
def initialize(foo: nil, bar: 456)
super(foo: foo)
@bar = bar
end
end
Наверняка есть какой-то более Ruby-подобный способ сделать это?