2017-11-28 3 views
2

私は店をimmutableとして扱うreduxストアを実装しています。したがって、店は次のようになります。dartのオプションの名前付きパラメータが指定されているかどうかを判別する方法はありますか?

class State { 
    final String firstname; 
    final String lastname; 

    State(this.firstname, this.lastname); 

    State.initial() 
     : this.firstname = null, 
     this.lastname = null; 

    State copy({String firstname, String lastname}) => 
    new State(firstname ?? this.firstname, lastname ?? this.lastname); 
} 

これはすべて問題なく動作し、状態をコピーしてコピー内の個々のフィールドを置き換えることができます。

state.copy(firstname: "foo"); 

しかし、今ではフィールドをnullに戻すことはできません。

state.copy(firstname: null); 

は機能しません。

私も何かしようとした:

State copy({String firstname = this.firstname, String lastname = this.lastname}) => ... 

をしかしダートは、デフォルト値として非constのを許可していません。

答えて

3

あなたは、パラメータは、コールサイトで提供されていなかった、またはそれがデフォルトと同じ値で提供されたかどうかを区別するための方法はありません。この

const _noValueGiven = const Object(); 

class State { 
    ... 
    State copy({String firstName: _noValueGiven, String lastName: _noValueGiven}) { 
    if (identical(firstName, _noValueGiven)) { 
     firstName = this.firstName; 
    } 
    ... 
    } 
} 
+1

これはDart 2.0(ObjectからStringへの割り当て)では無効です。 '__notSpecified__'のようなセンチネル文字列を使用することもできます – matanlurey

+0

また、定数が正規化されているため、 'const Object()'は安全でないセンチネル値です。プログラム内の他の 'const Object()'は同じオブジェクトに評価されます。 – lrn

+0

これまでのところ、私はこのソリューションを使いました。それは素晴らしく、定型的なオーバーヘッドはあまりありませんでした。私は実際には文字列パラメータではなく、オブジェクトに対して使用しています。文字列の場合、私は空に設定するために ""、存在しないにはnullに行きます。私は正規化についてはあまり確信していませんが、私はその意味合いを完全に理解するためにはそれ以上のことをしなければならないと思います。 – Fabian

1

のようにファイルに特殊なマーカーを使用することができます値。あなたはこのような場合には、実際の引数として提供されにくい一つの値を選択する必要が

おそらく、空の文字列""(あなたは空の文字列が、それは無視されて提供し、有効な名前ではないことを言うことができます一方、nullを渡すことは名前を設定解除する方法です)。

意味のない値がない場合は、別のタイプのセンチネルを使用する必要があり、APIドキュメントに型やセンチネル値が漏れないように、そのタイプを受け入れることができます。あなたは、実装を隠すために、民間のサブクラスを使用することができ、それを行うために

abstract class State { 
    ... 
    State(String firstName, String lastName) = _State; 
    State copy({String firstName, String lastName}); 
} 
class _State implements State { 
    String firstName, lastName; 
    _State(this.firstName, this.lastName); 
    State copy({Object firstName = 0, Object lastName = 0}) { 
    if (firstName != null && firstName is! String) { 
     firstName = this.firstName; 
    } 
    if (lastName != null && lastName is! String) { 
     lastName = this.lastName; 
    } 
    return new _State(firstName, lastName); 
    } 
} 

この方法で、どのユーザーが非文字列引数を可能にするタイプを持っていないので、彼らならば、彼らは警告を取得します試してみて_State.copyコードは実際の引数には安全です。Stringnullという値を無視します。

nullは、引数を省略することを意味します。それは他のすべての人がメソッドに呼び出しを転送することをはるかに簡単にします。それ以外の場合は、パラメータが渡されたかどうかを検出する必要もあります。この場合、おそらくnullの代わりに空の値を表すために空の文字列を使用し、nullを「引数が渡されていません」というマーカーにします。

関連する問題