Я все еще очень плохо знаком с Ruby (читаю Pickaxe и большую часть времени провожу в irb
), и теперь, когда я знаю, что можно исправлять классы в Ruby, мне интересно, когда это можно сделать в частности, можно ли исправлять базовые классы Ruby. Например: я ответил на другой вопрос Ruby здесь , где автор хотел узнать, как вычесть часы из DateTime
. Поскольку класс DateTime
, по-видимому, не обеспечивает эту функциональность, я опубликовал ответ, который исправляет классы DateTime
и Fixnum
как возможное решение. Это код, который я отправил:
require 'date'
# A placeholder class for holding a set number of hours.
# Used so we can know when to change the behavior
# of DateTime#-() by recognizing when hours are explicitly passed in.
class Hours
attr_reader :value
def initialize(value)
@value = value
end
end
# Patch the #-() method to handle subtracting hours
# in addition to what it normally does
class DateTime
alias old_subtract -
def -(x)
case x
when Hours; return DateTime.new(year, month, day, hour-x.value, min, sec)
else; return self.old_subtract(x)
end
end
end
# Add an #hours attribute to Fixnum that returns an Hours object.
# This is for syntactic sugar, allowing you to write "someDate - 4.hours" for example
class Fixnum
def hours
Hours.new(self)
end
end
Я пропатчил классы, потому что думал, что в этом случае это приведет к ясному и краткому синтаксису для вычитания фиксированного количества часов из DateTime
. В частности, вы могли бы сделать что-то подобное в результате кода выше:
five_hours_ago = DateTime.now - 5.hours
Который кажется довольно приятным для понимания и легким для понимания; однако я не уверен, стоит ли возиться с функциональностью оператора DateTime
-
.
Единственные альтернативы, которые я могу придумать для этой ситуации:
1. Просто создайте новый DateTime
объект на лету, вычисляя новое значение часа в вызове на new
new_date = DateTime.new(old_date.year, old_date.year, old_date.month, old_date.year.day, old_date.hour - hours_to_subtract, date.min, date.sec)
2. Напишите служебный метод, который принимает DateTime
и количество часов, которое нужно вычесть из него
По сути, просто метод обтекания (1):
def subtract_hours(date, hours)
return DateTime.new(date.year, date.month, date.day, date.hour - hours, date.min, date.sec)
end
3. Добавьте новый метод к DateTime
вместо изменения существующего поведения #-()
Возможно, новый метод DateTime#less
, который может работать вместе с патчем Fixnum#hours
, чтобы разрешить синтаксис, подобный этому:
date.less(5.hours)
<Ч />
Однако, как я уже упоминал, я применил подход к исправлению, потому что думал, что это привело к гораздо более выразительному синтаксису.
Что-то не так с моим подходом, или я должен использовать одну из трех альтернатив (или другую, о которой я не думал), чтобы сделать это? У меня такое ощущение, что исправление становится моим новым «молотком» для проблем в Ruby, поэтому я хотел бы получить некоторую обратную связь о том, делаю ли я что-то «Ruby way» или нет.