5

文字列値と int 値 (それぞれコマンド出力と終了コード) を公開するクラスがあります。to_sandを介してそれらを公開することに加えて、次のようにandto_iも使用しています。to_strto_int

class Status
  def to_s
    @output
  end
  alias :to_str :to_s

  def to_i
    @status.exitstatus
  end
  alias :to_int :to_i
end

この背後にある私の考えは、このオブジェクトをできるだけ多くの状況で使用できるようにすることです。文字列または整数に強制可能にすると、その使いやすさが向上します。たとえば、オブジェクトを文字列と連結できます。

a_string = "Output was: " + results

(これを int 強制の例として使用したかったのですが、Fixnum.+ が気に入らないため、実際には機能しません:)

an_int = 1 + results

私がこれまでに読んだものはすべて、これはおそらく「悪い」ことだと言っています。共通のテーマは次のようなりto_sます。to_ito_strto_int

私のクラスが「基本的に」文字列でも整数でもないことは間違いありません。ただし、このルールにはいくつかの問題があります。

  1. クラスの柔軟性/使いやすさが低下します。例: Status.to_str がなければ、String.+ を使用して Status 出力を他の文字列と連結することはできませんでした。
  2. ダックタイピングの精神に反しているようです。オブジェクトのユーザー (つまり、パラメータとしてそれを取得するメソッド) は、そのオブジェクト何であるかを気にするべきではなく、何ができるかだけを気にする必要があります。(この場合、"do" は "string/int として表現できる" という意味です。)
  3. 「基本的には文字列/整数です」という議論は、私にはかなりあいまいです。たとえば、それFloat.to_intがよく言及されていることがわかります。話は、浮動小数点数には常に整数コンポーネントto_intがあるため、有効な方法であるということです。ただし、これは間違っていると思います: Float は整数ではありません(整数以外のコンポーネントがあるため)。Float を (切り捨てにより) 整数に合法的に変換できますが、(終了コード以外のすべての情報を「切り捨てる」ことにより) Status も整数に変換できると言えます。

だから、私の質問は次のとおりです。実装に実際の(つまり、実際的な)害to_strはありto_intますか?


更新: Jörg W Mittag は、私に何かを考えさせた例を示しました。質問を言い換えると、既に/を持っているのに、本当にto_str/を持つ必要があるのでしょうか? (特定のメソッドがすでに以上を期待しているという事実に加えて)to_intto_sto_ito_strto_s

たとえば、Jörg の Array.join の例では、配列メンバーは to_s を介して変換され、セパレータは to_str を介して変換されます。しかし、これは本当に必要ですか?代わりに Array.join がseparator.to_s を呼び出すと、より多くのオブジェクト (例: 整数、シンボルなど) を正常に渡すことができ、より多くの柔軟性を得ることができます。Ruby は、この分離によってメリットがありますか?

4

2 に答える 2

8

クラスの柔軟性/使いやすさが低下します。例: をString#+持っていない場合、ステータス出力を他の文字列と連結するために使用できませんでしStatus#to_strた。

文字列の連結は一義的な Ruby であるため、これは悪い例です。文字列補間が推奨される方法です。

a_string = "Output was: #{results}"

文字列補間は補間された式の結果を実際に呼び出すため、これは機能します™ 。to_s

ダックタイピングの精神に反しているようです。オブジェクトのユーザー (つまり、パラメータとしてそれを取得するメソッド) は、そのオブジェクト何であるかを気にするべきではなく、何ができるかだけを気にする必要があります。(この場合、"do" は "string/int として表現できる" という意味です。)

「文字列/整数として表現できる」というのは実際には動作ではないと主張します。IOW:「オブジェクトができること」は特定のコンテキストでの興味深い動作に関するものであり、「文字列/整数として表現できる」はあまり興味深い動作ではありません。

「Status IS-A Integer」(本質的にはこれがto_int意味すること) と言えば、たとえば、それを使って算術演算を行うことができるということになります。しかし、 「見つからないファイルに 42 を追加する」とはどういう意味でしょうか? 成功の対数とは何ですか? 失敗の平方根とは何ですか?

上記の文字列補間の例で興味深いのは、「表示できる」という動作です。そして、それは基本的に実装することによって示されます#to_s。OTOH という 2 つの文字列を連結するには、2 つの文字列が必要です。

「基本的には文字列/整数です」という議論は、私にはかなりあいまいです。たとえば、それFloat#to_intがよく言及されていることがわかります。話は、浮動小数点数には常に整数コンポーネントto_intがあるため、有効な方法であるということです。ただし、これは間違っていると思います: Float は整数ではありません(整数以外のコンポーネントがあるため)。Float を (切り捨てにより) 整数に合法的に変換できますが、(終了コード以外のすべての情報を「切り捨てる」ことにより) Status も整数に変換できると言えます。

繰り返しますが、これはかなり弱い議論です。なぜなら、私は実際にあなたに同意するからです。それは間違っています。

ドイツ法には、把握が難しく非直感的な原則がありますが、ここでは完全に当​​てはまると思います。それは「Keine Gleichheit im Unrecht」(間違いに平等はない)と呼ばれています。それは、憲法で認められた平等の基本的権利が、法律の範囲内でのみ適用されることを意味します。別の言い方をすれば、OJ は殺人を合法化していません。

つまり、Ruby コア ライブラリにくだらないコードがあるからといって (そして、私を信じてください、たくさんあります)、あなたもがらくたを書くようになるわけではありません :-)

この特定のケースでは、Float#to_intは明らかに間違っており、存在すべきではありません。のサブタイプでFloat はありませんInteger。一見、正反対、つまり正しいように見えますInteger#to_floatが、実際にはそうではありません。Ruby では、Integers は任意の精度を持ちますが、Floats は固定の精度を持ちます。を実装することは有効ですが、 s は魔法のようにとの間で変換できるため、メソッドは「魔法のように」現れたり消えたりするFixnum#to_floatため、悪い考えです。IntegerFixnumBigInteger#to_float

最終的に と の違いを理解するのに役立ったの、セパレーターオブジェクトで区切られた配列の要素を出力することです。これは、配列の各要素と区切り記号を呼び出すことによって行われます。なぜそれが一方を呼び出し、もう一方を呼び出すのかを理解したら、基本的に設定は完了です。to_xto_xyzArray#jointo_sto_strto_sto_str

(あなたのコメントはFloat#to_intすでにあなた理解していることを示していますが。)


補足: 代数コンテキストでのダブル ディスパッチの場合、Ruby は実際に#coerceプロトコルを使用します。したがって、この1 + a_status例を機能させたい場合は、 を実装する必要がありますStatus#coerce。しかし、しないでください。

于 2009-11-12T02:05:25.677 に答える
4

ダックタイピングの精神により、だれかが Status オブジェクトのソース コードを調べて、何が返されているかを調べようとすることはありません。

個人的には、テキスト結果と終了ステータスを 2 つのインスタンス メソッドで公開する必要があると思います。

class Status

  ...

  def message
    @output
  end

  def exit_status
    @status.exitstatus
  end

end

そして、次のように使用します

a_string = "Output was: " + results.message
a_int    = 1 + results.exit_status

これは、コードを読んでいる人なら誰でもすぐに理解できます。

于 2009-11-11T21:21:14.030 に答える