どちらも同じケースで使用できるようです。型チェックなどで異なる表現や微妙な点はありますか?
Dartプログラミング言語仕様、第3版 のセクションType dynamicは、次のように述べています。
動的型には、名前付きパラメーターの可能なすべての組み合わせで、可能なすべての識別子とアリティに対するメソッドがあります。これらのメソッドはすべて、戻り値の型がdynamicであり、それらの仮パラメーターはすべて、型がdynamicです。タイプdynamicには、可能なすべての識別子のプロパティがあります。これらのプロパティはすべてダイナミック型です。
つまり、dynamic
型付き変数でメソッドを呼び出しても警告は表示されません。 Object
として型指定された変数には当てはまりません。例えば:
dynamic a;
Object b;
main() {
a = "";
b = "";
printLengths();
}
printLengths() {
// no warning
print(a.length);
// warning:
// The getter 'length' is not defined for the class 'Object'
print(b.length);
}
実行時には、違いは見られないと思います。
dynamic
のもう1つの見方は、それが実際には型ではないということです。これは型チェックをオフにして、静的型システムに「信頼してください、私がやっていることを知っています」と伝える方法です。 _dynamic o;
_を書き込むと、型指定されていない変数が宣言されます。代わりに、「型チェックされていない」とマークされます。
_Object o = something;
_を書くと、o
であること以外はObject
について何も仮定できないことをシステムに伝えます。これらのメソッドはtoString
で定義されているため、hashCode
およびObject
を呼び出すことができますが、o.foo()
を実行しようとすると、警告が表示されます-できますあなたがそれを行うことができるとは思わないので、コードがおそらく間違っていることを警告します。
_dynamic o = something
_と書くと、システムに何も想定せず、何もチェックしないよう指示します。 o.foo()
と書いても、警告は出されません。 「o
に関連するものはすべてOKです。信頼してください、私が何をしているか知っています」とあなたは言ったので、o.foo()
はOKだと思います。
大きな力には大きな責任が伴います-変数の型チェックを無効にした場合、何も問題がないことを確認する必要があります。
実用的な違いに関するアレクサンドルの回答に追加すると、2つの間に意味上の違いもあり、正しいものを使用すると、他のプログラマーに意図をよりよく伝えるのに役立ちます。
Object
を使用すると、使用している型がわかっており、それがObject
であると言っていることになります。例えば:
int getHashCode(Object obj) {
return obj.hashCode;
}
hashCode
はObject
のプロパティであるため、Object
をパラメーターの型として使用し、関数がObject
のすべての型を受け入れることを指定します。
一方、dynamic
を使用すると、Dartシステムは使用するタイプを適切に表現できなくなります。
void setEmail(dynamic email) {
if (email is Email) {
_email = email;
} else if (email is String) {
_email = new Email.fromString(email);
}
}
Dartは現在ユニオンタイプをサポートしていないため、タイプEmail | String
を表現する方法がないため、dynamic
を使用してすべてのタイプを受け入れ、タイプが1である場合のみを処理する必要があります。興味があります。
また、拡張メソッドは動的では正しく機能しませんが、オブジェクトでは問題なく機能することにも気付きました。
// I used to have the extension on dynamic and had
// problems that didn't occur when using the same extension on Object
extension UtilExtensions on Object {
bool get isStringNotEmpty => this is String && (this as String).isNotEmpty;
String get asStringNotEmpty => isStringNotEmpty ? this as String : null;
bool get isIntNotZero => this is int && (this as int) != 0;
int get asIntNotZero => isIntNotZero ? this as int : null;
Map<String, Object> get asPair {
if (this != null && this is Map) {
return (this as Map).cast<String, Object>();
}
return null;
}
Map<String, Object> get asFullPair {
if (this != null && this is Map) {
var ret = (this as Map).cast<String, Object>();
for (var key in ret.keys) {
var val = ret[key];
if (val is Map) {
ret[key] = val.asFullPair;
}
}
return ret;
}
return null;
}
}