Android学Dart学习笔记第二十一节 类-点的简写

前置

使用此功能需要sdk版本>3.10, 我把sdk上传到了csdn,3.10.6最新版本,需要的点击下载

trae不知道咋回事,升级sdk后一直不能自动识别,被迫手动添加了下面的配置

概述

点号简写语法 ** .foo** 让你可以省略类型编写更简洁的 Dart 代码,当编译器能从上下文中推断出类型时。这为访问枚举值、静态成员或构造函数提供了一种简洁的替代写法,而不需要写完整的 ContextType.foo

本质上,点号简写允许表达式以下列之一开始,然后可以选择性地链式调用其他操作:

看看下面的例子:

dart 复制代码
// Use dot shorthand syntax on enums:
enum Status { none, running, stopped, paused }

Status currentStatus = .running; // Instead of Status.running

// Use dot shorthand syntax on a static method:
int port = .parse('8080'); // Instead of int.parse('8080')

// Uses dot shorthand syntax on a constructor:
class Point {
  final int x, y;
  Point(this.x, this.y);
  Point.origin() : x = 0, y = 0;
}

Point origin = .origin(); // Instead of Point.origin()

下面我输入了.之后,自动提示了int的所有静态方法

上下文类型的作用

这是 Dart 的一个语法糖,让你可以省略枚举类型或静态成员的前缀,只用 .成员名 的形式。

编译器根据代码所处的位置,推断出"这里应该是什么类型"。

dart 复制代码
void main() {
  // 传统写法
  Status currentStatus1 = Status.running;
  
  // 使用点简写
  Status currentStatus2 = .running;  // 编译器知道这里需要 Status 类型
}

不知道你发现了没有,之所以可以省略类型前缀,是因为类型定义时使用了明确的类型 ,比如 int、Status。

在使用.时,一定是以及有了明确的主体类型。

词汇结构和句法

静态成员简写是一种以点号(.)开头的表达式。当类型可以从周围的上下文推断出来时,这种语法为访问静态成员、构造函数和枚举值提供了一种简洁的方式。

Enums

点简写语法的一个主要且强烈推荐的使用场景是搭配枚举类型,尤其在赋值语句和 switch 语句中,因为在这些情况下枚举类型是非常明确的。

dart 复制代码
enum LogLevel { debug, info, warning, error }

/// Returns the color code to use for the specified log [level].
String colorCode(LogLevel level) {
  // Use dot shorthand syntax for enum values in switch cases:
  return switch (level) {
    .debug => 'gray', // Instead of LogLevel.debug
    .info => 'blue', // Instead of LogLevel.info
    .warning => 'orange', // Instead of LogLevel.warning
    .error => 'red', // Instead of LogLevel.error
  };
}

// Example usage:
String warnColor = colorCode(.warning); // Returns 'orange'

Named constructors

点简写语法对于调用具名构造函数或工厂构造函数非常有用。当需要向泛型类的构造函数提供类型参数时,这种语法同样适用。

dart 复制代码
class Point {
  final double x, y;
  const Point(this.x, this.y);
  const Point.origin() : x = 0, y = 0; // Named constructor

  // Factory constructor
  factory Point.fromList(List<double> list) {
    return Point(list[0], list[1]);
  }
}

// Use dot shorthand syntax on a named constructor:
Point origin = .origin(); // Instead of Point.origin()

// Use dot shorthand syntax on a factory constructor:
Point p1 = .fromList([1.0, 2.0]); // Instead of Point.fromList([1.0, 2.0])

// Use dot shorthand syntax on a generic class constructor:
List<int> intList = .filled(5, 0); // Instead of List.filled(5, 0)

Unnamed constructors

点简写 .new 提供了一种简洁的方式来调用类的未命名构造函数。这在类型已显式声明的字段或变量赋值场景中尤为实用。

该语法能有效简化重复的类字段初始化代码,如下方使用点简写后的示例所示。它不仅适用于带参数或不带参数的构造函数,还能根据上下文自动推断所有泛型类型参数。

未使用.简写时:

dart 复制代码
class _PageState extends State<Page> {
  late final AnimationController _animationController = AnimationController(
    vsync: this,
  );
  final ScrollController _scrollController = ScrollController();

  final GlobalKey<ScaffoldMessengerState> scaffoldKey =
      GlobalKey<ScaffoldMessengerState>();

  Map<String, Map<String, bool>> properties = <String, Map<String, bool>>{};
  // ...
}

使用.简写后:

dart 复制代码
// Use dot shorthand syntax for calling unnamed constructors:
class _PageState extends State<Page> {
  late final AnimationController _animationController = .new(vsync: this);
  final ScrollController _scrollController = .new();
  final GlobalKey<ScaffoldMessengerState> scaffoldKey = .new();
  Map<String, Map<String, bool>> properties = .new();
  // ...
}

省略了相当多的重复代码。

Static members

您可以使用点简写语法来调用静态方法或访问静态字段/Getter。编译器会根据表达式的上下文类型推断出目标类。

dart 复制代码
// Use dot shorthand syntax to invoke a static method:
int httpPort = .parse('80'); // Instead of int.parse('80')

// Use dot shorthand syntax to access a static field or getter:
BigInt bigIntZero = .zero; // Instead of BigInt.zero

Constant expressions

在常量上下文中,若访问的成员是编译时常量,也可以使用点简写语法。这在访问枚举值或调用常量构造函数时十分常见。

dart 复制代码
enum Status { none, running, stopped, paused }

class Point {
  final double x, y;
  const Point(this.x, this.y);
  const Point.origin() : x = 0.0, y = 0.0;
}

// Use dot shorthand syntax for enum value:
const Status defaultStatus = .running; // Instead of Status.running

// Use dot shorthand syntax to invoke a const named constructor:
const Point myOrigin = .origin(); // Instead of Point.origin()

// Use dot shorthand syntax in a const collection literal:
const List<Point> keyPoints = [.origin(), .new(1.0, 1.0)];
// Instead of [Point.origin(), Point(1.0, 1.0)]

规则和限制

简写语法依赖于明确的上下文类型,这导致了您需要了解夏敏几条特定规则和限制。

调用链中需要清晰的上下文

虽然可以在点简写语法后进行链式操作(如方法调用或属性访问),但整个表达式仍需基于上下文类型进行验证。

编译器首先会利用上下文来确定点简写对应的目标,而链式操作中的任何后续操作都必须返回与初始上下文类型相匹配的值。

dart 复制代码
// .fromCharCode(72) resolves to the String "H",
// then the instance method .toLowerCase() is called on that String.
String lowerH = .fromCharCode(72).toLowerCase();
// Instead of String.fromCharCode(72).toLowerCase()

print(lowerH); // Output: h

非对称等式检查

== 和 != 运算符对点简写语法有一条特殊规则。当点简写直接用于等式检查的右侧时,Dart 会使用左侧的静态类型来确定该简写对应的类或枚举。

例如,在表达式 myColor == .green 中,变量 myColor 的类型被用作上下文。这意味着编译器会将 .green 解释为 Color.green。

dart 复制代码
enum Color { red, green, blue }

// Use dot shorthand syntax for equality expressions:
void allowedExamples() {
  Color myColor = .red;
  bool condition = true;

  // OK: `myColor` is a `Color`, so `.green` is inferred as `Color.green`.
  if (myColor == .green) {
    print('The color is green.');
  }

  // OK: Works with `!=` as well.
  if (myColor != .blue) {
    print('The color is not blue.');
  }

  // OK: The context for the ternary is the variable `inferredColor`
  // being assigned to, which has a type of `Color`.
  Color inferredColor = condition ? .green : .blue;
  print('Inferred color is $inferredColor');
}

点简写必须位于 == 或 != 运算符的右侧 。同时,也不允许将其与更复杂的表达式(例如条件表达式)进行比较。
左侧必须是明确的类型

下面是错误案例

dart 复制代码
enum Color { red, green, blue }

void notAllowedExamples() {
  Color myColor = Color.red;
  bool condition = true;

  // ERROR: The shorthand must be on the right side of `==`.
  // Dart's `==` operator is not symmetric for this feature.
  if (.red == myColor) {
    print('This will not compile.');
  }

  // ERROR: The right-hand side is a complex expression (a conditional expression),
  // which is not a valid target for shorthand in a comparison.
  if (myColor == (condition ? .green : .blue)) {
    print('This will not compile.');
  }

  // ERROR: The type context is lost by casting `myColor` to `Object`.
  // The compiler no longer knows that `.green` should refer to `Color.green`.
  if ((myColor as Object) == .green) {
    print('This will not compile.');
  }
}

表达式语句不能以点号 . 开头

为避免将来可能出现的解析歧义,不允许表达式语句以 . 标记开头。

看下面的例子(我个人感觉这是个废话,以点开头肯定没有明确的上下文类型)

dart 复制代码
class Logger {
  static void log(String message) {
    print(message);
  }
}

void main() {
  // ERROR: An expression statement can't begin with `.`.
  // The compiler has no type context (like a variable assignment)
  // to infer that `.log` should refer to `Logger.log`.
  .log('Hello');
}

对联合类型的有限处理

虽然对可空类型 (T?) 和 FutureOr 有特殊处理,但其支持是有限的。

对于可空类型 (T?),可以访问 T 的静态成员,但不能访问 Null 的静态成员。

对于 FutureOr,可以访问 T 的静态成员(主要是为了支持异步函数返回值),但不能访问 Future 类本身的静态成员。

结语

感觉非常有用,省略了很多的重复代码,希望你看到这种写法的时候不会懵,最后记住他的版本支持,否则你的伙伴可能会对你有意见哈。

相关推荐
黑客思维者2 小时前
机器学习009:监督学习【回归算法】(岭回归)-- 给模型一个“清醒”的约束
学习·机器学习·回归·监督学习·岭回归
深蓝海拓2 小时前
PySide6从0开始学习的笔记(十一) QSS 属性选择器
笔记·python·qt·学习·pyqt
不爱吃糖的程序媛2 小时前
Flutter-OH OAuth 鸿蒙平台适配详细技术文档
javascript·flutter·harmonyos
中屹指纹浏览器2 小时前
2025技术解析:分布式指纹协同管理技术底层实现与规模化运营逻辑
经验分享·笔记
庄雨山2 小时前
深入解析Flutter动画体系:原理、实战与开源鸿蒙OpenHarmony对比
flutter·openharmonyos
kirk_wang2 小时前
Flutter GPUImage 库在鸿蒙平台的 GPU 图像滤镜适配实战
flutter·移动开发·跨平台·arkts·鸿蒙
风123456789~2 小时前
【健康管理】第8章 身体活动基本知识 2/2
笔记·考证·健康管理
QQ12958455042 小时前
ThingsBoard-修改Android APP应用程序名和描述
android·物联网·iot
代码游侠2 小时前
学习笔记——Linux进程间通信(IPC)
linux·运维·笔记·学习·算法