5

「ダックタイピング」の意味を誤解していないことを願っていますが、私が読んだことから、オブジェクトがどのタイプ/クラスであるかではなく、メソッドにどのように応答するかに基づいてコードを記述する必要があることを意味します。

コードは次のとおりです。

def convert_hash(hash)
  if hash.keys.all? { |k| k.is_a?(Integer) }
    return hash
  elsif hash.keys.all? { |k| k.is_a?(Property) }
    new_hash = {}
    hash.each_pair {|k,v| new_hash[k.id] = v}
    return new_hash
  else
    raise "Custom attribute keys should be ID's or Property objects"
  end
end

私が望むのは、キーが ActiveRecord オブジェクトの ID を表す整数であるハッシュになるようにすることです。all?IDを取得する必要があるかどうかを判断するために、ハッシュキーを2回反復処理する必要があるのは特に好きではありません。

もちろん、このコードを改善するための他の提案も受け入れます:)

4

3 に答える 3

11

このメソッドをどのように記述するかは、通常のプログラム実行中に例外がスローされることを期待するかどうかによって異なります。エンドユーザーに表示される可能性があるため、読み取り可能な例外メッセージが必要な場合は、手動で例外メッセージをスローするのが理にかなっています。それ以外の場合は、次のようにします。

def convert(hash)
    new_hash = {}
    hash.each_pair { |k,v| new_hash[ k.is_a?(Integer) ? k : k.id ] = v }
    return new_hash
end

これはまったく同じことを達成し、配列キーに id フィールドがない場合でも例外が発生します。さらに良いことに、これはもう少しダックタイピングを使用します。これは、id フィールドを持つものはすべて受け入れられるためです。これは、何かがプロパティであることを明示的にチェックするよりも優れています。これにより、特に単体テストの際に、コードがより柔軟になります。

整数オブジェクトの明示的なチェックはまだありますが、この種の時折の特殊なケースは、特に組み込みデータ型をチェックする場合は通常許容されます。

于 2008-10-16T17:32:52.147 に答える
3

ダックタイピングは、実際にはポリモーフィズムの微妙なバージョンにすぎません。Java のような静的に型付けされた言語では、特定の変数が受け入れることができるすべてのメソッドをコンパイラに伝える明示的なインターフェイスを作成する必要があります。Ruby のような動的言語では、インターフェイスは依然として抽象的な意味で存在し、暗黙的です。

問題は、2 つの異なるデータ構造を 1 つのメソッドに受け入れているという事実です。ダックタイピングを機能させる方法は、メソッドに渡されるすべてのオブジェクトが同じ規約に従うことを要求することです (つまり、常に [Foo] オブジェクトへの整数のハッシュです)。正しい構造は、クライアント コードの仕事です。これは、単純なラッパー クラスまたは elseif 句の本体だけで構成される変換関数を使用して非常に簡単に実行できます。

要するに、メソッドを呼び出す人は、自分のパラメーターがすべて、メソッドが期待するとおりに鳴るようにする必要があります。そうでない場合は、七面鳥をアヒルのように鳴らす方法を見つけなければならないのは彼であり、あなたではありません。

于 2008-10-16T17:59:09.363 に答える
0

私が欲しいのは、キーがActiveRecordオブジェクトのIDを表す整数であるハッシュで終わることを確認することです。

ハッシュを作成/挿入するときに、おそらくそれを確認する必要があります。あなたはこのようなことを試すことができます:

h = {}
def h.put obj
  self [obj.id] = obj
終わり

または多分

h = {}
defh。[]=キー、値
  key == value.idでない限り、「地獄」を上げる
  素晴らしい
終わり
于 2008-10-17T11:31:27.727 に答える