Dart 3.15 新特性:this 终于支持类型提升了

发布时间:2026/10/21 2:37:11
Dart 3.15 新特性:this 终于支持类型提升了 这次 Dart 3.15 有个改动虽然不大但我感觉算是解决了 Dart 类型系统里一个存在多年的不合理限制编译器明明已经知道当前对象是什么类型但是就是不给开发者直接按照这个类型用它。从 3.15 开始this终于可以像局部变量一样根据is判断、空值检查之类条件也可以自动改变自己的静态类型class Shape { void describe() { var self this; if (self is Circle) { print(radius ${self.radius}); } } } ​ class Circle extends Shape { final double radius; Circle(this.radius); }比如这里Shape是父类Circle是子类子类独有一个radius属性如果执行Circle(10).describe();虽然describe()定义在Shape里面但是实际执行它的对象是Circle所以进入方法的时候this的声明静态类型是Shapethis在运行时指向的对象是Circle经过is Circle判断之后编译器知道当前对象确实是Circle实际上以前的问题刚好就是出在第三点以前的 Dart 就算知道判断结果也不会修改this的静态类型所以如果直接写会变异错误class Shape { void describe() { if (this is Circle) { print(this.radius); // 旧版本编译错误 } } }编译器还是按照Shape查找radius自然就会报错因为Shape根本没有这个字段。而为了绕过限制开发者必须先写var self this然后让self参与类型提升这是因为 Dart 以前只支持特定变量的类型提升不支持直接提升this。而到了 Dart 3.15 现在这个代码终于可以正常工作了在if成立的分支里this的静态类型可以由Shape提升为Circle。class Shape { void describe() { if (this is Circle) { print(radius $radius); } } }而且不只是this.radius可以访问直接写radius也可以因为类实例方法里radius这样的隐式实例成员访问编译器也会考虑已经提升的this类型也就是父类方法可以直接访问经过类型判断确认的子类成员不用反复强制转换。其实就是变化的是编译器在对应代码分支中理解的静态类型不是对象本身的实际类型。另一个更实用的场景是 Nullable ExtensionDart 允许给可空类型添加 Extension例如int?extension NullableInt on int? { bool get isEvenOrNull { final self this; ​ if (self null) { return true; } ​ return self.isEven; } }这里this的类型是int?也就是既可能是整数也可能是null按照常规的空安全规则检查self null并提前返回以后后面的self就会从int?提升成int可以直接使用isEven。但是以前直接检查this编译器不会完成这种提升必须额外定义一个self。而现在 Dart 3.15 可以直接写extension NullableInt on int? { bool get isEvenOrNull { if (this null) return true; ​ return isEven; } } ​ void main() { int? a 4; int? b 3; int? c; ​ print(a.isEvenOrNull); // true print(b.isEvenOrNull); // false print(c.isEvenOrNull); // true }这里有两个变化首先if (this null) return true之后编译器知道剩余路径的this必然是非空int其次return isEven里面隐式使用的this也会享受到这次提升最重要的是Extension 的接收对象完整参与 Dart 的空安全控制流分析 以前局部变量能做到的事情现在 Extension 里的this也能做了。类似专业的场景这里的debugInfo写在父类PageState里面但是能够通过this is Loaded和this is Failed直接访问子类的items、message属性sealed class PageState { const PageState(); ​ String get debugInfo { if (this is Loaded) { return 加载成功: ${items.length} 条数据; } ​ if (this is Failed) { return 加载失败: $message; } ​ return 加载中; } } ​ class Loading extends PageState { const Loading(); } ​ class Loaded extends PageState { final ListString items; const Loaded(this.items); } ​ class Failed extends PageState { final String message; const Failed(this.message); }这种机制对 Flutter 中的状态基类、事件体系、插件扩展、基于继承的组件封装都挺有帮助的尤其是存在大量类型分支判断的代码。当然上面的例子只是为了演示类型提升实际业务如果已经用sealed class、switch模式匹配或者可以通过多态完成状态处理一般其实不需要为了用这个新特性而改回一大堆if (this is Xxx)。至于为什么 Dart 到 3.15 才支持这里其实涉及 Dart 类型系统长期以来对类型提升的谨慎因为 Dart 的类型提升不是看到一个判断就无条件修改类型实际上编译器还需要确认被检查的值在后续代码中是否足够稳定比如class Test { int? value; ​ void run() { if (value ! null) { // value 仍然可能变化 } } }value是一个可变成员编译器不能因为检查过一次就永远假定它非空对 Getter 来说连续两次调用甚至可能返回不同结果。而this本质上有个明显优势一个实例方法执行期间当前接收对象不会突然变成另一个对象所以只要条件能够证明当前对象满足某个类型编译器就可以在相应控制流中安全地使用这个信息。这里和 Dart 3.2 的字段类型提升还是有区别的对比Dart 3.2Dart 3.15局部变量类型提升支持支持私有final字段提升支持支持this is SubType后提升this不支持支持Nullable Extension 中提升this不支持支持隐式this成员访问使用提升结果不支持支持等于是Dart 3.2 解决的是一部分稳定字段的类型提升问题3.15 进一步补上了当前对象本身的类型提升。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询