unsafe_variance
不安全的型變:在非共變位置中有型別變數。
詳細資訊
#類型在非共變位置包含封閉類別、Mixin 或列舉的類型參數的實例變數,很可能因為類型檢查失敗而導致執行階段錯誤。例如,在 class C<X> {...}
中,void Function(X) myVariable;
形式的實例變數可能會導致此類執行階段錯誤。
對於回傳類型在封閉宣告的類型參數中具有非共變出現的 getter 或方法來說,情況也是如此。
此 Linter 標記此類成員宣告。
不良範例
class C<X> {
final bool Function(X) fun; // LINT
C(this.fun);
}
void main() {
C<num> c = C<int>((i) => i.isEven);
c.fun(10); // Throws.
}
問題在於 X
作為 fun
類型的參數類型出現。
減少執行階段類型錯誤可能性的其中一種方法,是確保非共變成員 fun
僅在 this
上使用。我們無法嚴格執行此操作,但我們可以將其設為私有,並新增一個轉發方法 fun
,以便我們可以在同一個程式庫中在本機檢查是否滿足此約束。
較佳範例
class C<X> {
// ignore: unsafe_variance
final bool Function(X) _fun;
bool fun(X x) => _fun(x);
C(this._fun);
}
void main() {
C<num> c = C<int>((i) => i.isEven);
c.fun(10); // Succeeds.
}
完全安全的方法需要 Dart 尚未擁有的功能,即靜態檢查的型變。有了它,我們可以指定類型參數 X
是不變的 (inout X
)。
即使沒有靜態檢查型變的支援,也有可能模擬不變性。這對子類型的建立施加了一些限制,但忠實地提供了 inout
會給出的類型。
良好範例
typedef Inv<X> = X Function(X);
typedef C<X> = _C<X, Inv<X>>;
class _C<X, Invariance extends Inv<X>> {
// ignore: unsafe_variance
final bool Function(X) fun; // Safe!
_C(this.fun);
}
void main() {
C<int> c = C<int>((i) => i.isEven);
c.fun(10); // Succeeds.
}
使用此方法,C<int>
不是 C<num>
的子類型,因此 c
必須具有不同的宣告類型。
另一種可能性是宣告變數具有安全但更通用的類型。然後可以安全地使用變數本身,但每次調用都必須在執行階段檢查。
誠實範例
class C<X> {
final bool Function(Never) fun;
C(this.fun);
}
void main() {
C<num> c = C<int>((int i) => i.isEven);
var cfun = c.fun; // Local variable, enables promotion.
if (cfun is bool Function(int)) cfun(10); // Succeeds.
if (cfun is bool Function(bool)) cfun(true); // Not called.
}
啟用
#若要啟用 unsafe_variance
規則,請在您的 analysis_options.yaml
檔案中的 linter > rules 下新增 unsafe_variance
。
linter:
rules:
- unsafe_variance
如果您改為使用 YAML 地圖語法來配置 Linter 規則,請在 linter > rules 下新增 unsafe_variance: true
。
linter:
rules:
unsafe_variance: true
除非另有說明,否則本網站上的文件反映的是 Dart 3.7.1 版本。頁面上次更新於 2025-03-07。 檢視原始碼 或 回報問題。