4

カスタムセッターメソッドとゲッターメソッドを作成するためのRubyの標準的な方法は何でしょうか。通常、私はこれを経由attr_accessorして行いますが、DSLを作成するコンテキストにいます。DSLでは、セッターは次のように呼び出されます(=符号を使用するとローカル変数が作成されます)。

work do
 duration 15
 priority 5
end

したがって、次のように実装する必要があります。

def duration(dur)
 @duration = dur
end

ただし、これにより、ゲッターの実装が少し難しくなります。同じ名前で引数のないメソッドを作成すると、セッターが上書きされるだけです。

そこで、設定と取得の両方を行うカスタムメソッドを作成しました。

def duration(dur=nil)
 return @duration = dur if dur
 return @duration if @duration
 raise AttributeNotDefinedException, "Attribute '#{__method__}' hasn't been set"
end

これはそれについて行くのに良い方法ですか?テストケースの要点は次のとおりです。

Rubyカスタムゲッター&セッター

ありがとう!

4

4 に答える 4

9

トリッキーなケースは、期間をnilに設定する場合です。これを行うには2つの方法が考えられます

def duration(*args)
  @duration = args.first unless args.empty?
  @duration
end

人々が任意の数の引数を渡して、その数に基づいて何をすべきかを決定できるようにします。複数の引数が渡された場合にも、例外を発生させることができます。

別の方法は

def duration(value = (getter=true;nil))
  @duration = value unless getter
  @duration
end

これはデフォルトの引数を少し活用します。それらはほとんどすべての式にすることができます。

引数なしで呼び出された場合getterはtrueに設定されますが、引数が指定された場合(nilであっても)、デフォルト値は評価されません。ローカル変数スコープがどのように機能するかにより、最終的にgetterはnilになります。

少し賢すぎるかもしれませんが、メソッド本体自体はよりクリーンです。

于 2012-07-02T16:20:52.580 に答える
2

このような場合、私は基礎となるクラスをDSLから分離することを好みます。つまり、通常のアクセサを持つWorkクラスを作成しdurationますduration=。また、DSLを介してそのクラスを使用するには、次のように、状況に応じてアクセサーを呼び出すことができるもので作業インスタンスをラップします。

class AccessorMultiplexer

  def initialize(target)
    @target = target
  end

  def method_missing(method, *args)
    method = "#{method}=" unless args.empty?
    @target.send method, *args
  end

end

DSLを介してWorkクラスを使用する場合は常に、でラップしAccessorMultiplexer.new(work)ます。

ラッパーでのメタプログラミングに反対する場合は、を使用せずに同じことを行う特定のWorkDSLラッパーをいつでも作成できますmethod_missing。しかし、それは分離を維持し、DSL構文の癖によってWorkクラスが汚染されるのを防ぎます。DSLが邪魔になるコード内の別の場所でWorkクラスを使用することをお勧めします。熊手か台本か-誰が知っているか。

(コードレビューに関する私の回答から採用。)

于 2012-07-02T16:21:17.353 に答える
0

値が設定されていない場合にエラーが発生するのは奇妙に思えますが、それは私には問題ないようです。これは私が通常行うことです:

def duration(dur=nil)
 @duration = dur if dur
 @duration
end

ただし、これは単純なアプローチです。これは、この方法だけ@durationを使用することに戻ることができないことを意味します。nil

于 2012-07-02T16:13:25.180 に答える
0

私は通常これを行います

def duration dur='UNDEFINED'
  @duration = dur if dur != 'UNDEFINED'
  @duration
end

UNDEFINEDをお気に入りのものに置き換えることができます

于 2012-08-14T13:57:20.037 に答える