特定の値のセットの実装と、高度なチェックを備えたある種の汎用セットの使用


8

現在、JavaScriptのセット実装に取り​​組んでいます。これは、JavaまたはC#から知られているジェネリックをシミュレートする必要があります。その可変バージョン(設定値の追加/削除が可能)と不変バージョンが必要です。

私のコンストラクターの署名は次のようになります。

new GenericSet( 'number', [ 10, 20, 30 ] );

 // mutable set of mixed values (allows to add further values via "add")
 new MutableGenericSet( '*', [ 'foo', 42, {}, /./ ] );

または

// DataValues.prototype.equals will be used by the set for determining equality.
new GenericSet( { type: DataValue, valueComparison: 'equals' }, [ dv1, dv2, dv3 ] );

GenericSetだけか、タイプごとに1つのセット実装ですか?

当初、これの主な目的は、1つのタイプの値のセットを持つことでした。たとえば、データ値のみを受け入れるDataValuesSet。次に、DataValuesSetインスタンスを必要とする関数を使用してインターフェイスを定義できます。継承を使用することはできず(とにかく悪いことだと思います)、そのため、コンポジションを使用し、GenericSet / MutableGenericSetインスタンスを内部で使用します。

別のアプローチは、常にGenericSetを取得して実装し、使用することです。GenericSet.requireSetOfType( type )これは、セットのタイプが必要なタイプでない場合にエラーをスローします。この方法で行うことに対する私の懸念は、インターフェイスの定義がそれほど明確に見えないことです。

取る

/**
 * @param DataValuesSet dataValues
 */
function printDataValues( dataValues ) {
    if( !( dataValues instanceof DataValuesSet ) ) {
        throw Error( '...' );
    }
    // ...
}

/**
 * @param GenericSet<DataValue>
 */
function printDataValues( dataValues ) {
    // Throws error if dataValues is not a set or it it is a set with values of wrong type.
    GenericSet.requireSetOfType( dataValues, DataValue );
    // ...
}

おそらく@param GenericSet(DataValues) dataValues、2番目の選択肢を文書化するために使用しても大丈夫でしょうか?誰かが2番目のアプローチとの関連をさらに見ていますか、それとも別の提案がありますか?私にとって、2つ目はより直感的に見え、1つ目に対する懸念は、現時点では明確な利点が見当たらない一方で、コンストラクターでオーバーヘッドを増やすことです。


6
弱い型付けのJSのような言語でジェネリックが問題になるのはなぜですか?
ヤザド2015

1
これは、JavaScriptのような言語では不可能で、動的に型付けされます。TypeScriptのような型付きのJSバリアントを使用するだけです。
gardenhead 2017年

回答:


3

私はJavaScriptでこの種の問題を解決しようとしていましたが、JavaScriptの実装を複雑にするだけでした...まあ...何でも。Typescriptのようなものを使いたくない場合は、期待どおりに文書化してください。人々があなたの文書を無視するならば、彼らは未知の領域に入ります。

誰でも丸い穴に成形できるような四角い穴に丸いペグを押し込まないでください。それがJavaScriptです。それを受け入れる。戦うな、ベイビー。それを文書化し、コードの記述に戻ってください。


0

最初の例はもっと読みやすいと思います。誤って型指定されたセットに対してエラーがスローされることを意味するものではありません。この関数はをとると言っていますDataValueSet。コードで明示的であることは、明確さを追加します。

GenericSet.requireSetOfType印刷機能での型チェックの目的を難読化します。タイプのアイテムをチェックしているようDataValueです。


読みやすさは、ここで私にとって十分に強力な議論ではないようです。DataValuesSetvs を使用すると、どちらの場合でもドキュメントを完全に明確にすることができGenericSet<DataValue>ます。おそらくGenericSet.requireSetOfType、関数GenericSet.assertSetOfTypeや類似の名前を付ける代わりに、実際にはより明確になります。
Daniel AR Werner

0

あなたが提示するオプションを考えると、私は最初の解決策を好むでしょう。しかし、本当にJSスタイルのソリューションを実行したい場合は、オブジェクトが同じタイプのものであるか、混合タイプ(MakeStrictCollectionvs MakeMixedCollection)である必要があるかどうかにかかわらず、ビルダー関数を作成します。ビルダー関数では、指定したコレクションのすべてのメンバーの型が同じ型かどうかをテストし、エラーをスローするか、追加の型属性"type":"strict"vs を持つ各コンストラクターからオブジェクトを返します"type":"mixed"


それに加えて:

Typescriptを確認する必要があります。そして、一般的なコレクションを持っているあなたのニーズに合うように見えるパッケージがあります。


-1 MakeStrictCollection MakeMixedCollection。上記のコードの例に関しては、printDataValues関数は、指定されたオブジェクトがあったことを確認するために変化するinstanceof StrictCollectionと、そのタイプであることが確認されましたDataValuesGenericSet.requireSetOfTypeまさにそれかもしれません-したがって、あなたの提案はGenericSetアプローチの実装の詳細にすぎないようです。
Daniel AR Werner
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.