私はまだ Ruby に非常に慣れていません (つるはしを読み、ほとんどの時間を .NET に費やしています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)
DateTime
2. aと、そこから減算する時間数を受け入れるユーティリティ メソッドを作成します。
基本的に、方法 (1) の単なるラッパーです。
def subtract_hours(date, hours)
return DateTime.new(date.year, date.month, date.day, date.hour - hours, date.min, date.sec)
end
DateTime
3.の既存の動作を変更する代わりに、新しいメソッドを追加します#-()
おそらく、次のような構文を可能にするために、パッチとDateTime#less
一緒に機能する新しいメソッドです。Fixnum#hours
date.less(5.hours)
ただし、既に述べたように、パッチを適用するアプローチを採用したのは、より表現力豊かな構文が得られると考えたからです。
私のアプローチに何か問題がありますか、またはこれを行うために3つの選択肢の1つ(または私が考えていない別のもの)を使用する必要がありますか? パッチを適用することが Ruby の問題に対する新しい「ハンマー」になりつつあると感じているので、「Ruby のやり方」で物事を行っているかどうかについてフィードバックを得たいと思います。