dart-language-syntax

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

dart-advanced-syntax-and-patterns

Dart高级语法与模式

Goal

目标

Implements idiomatic Dart code leveraging advanced syntax, including pattern matching, records, generics, and sound null safety, to produce robust, type-safe, and concise applications. This skill assumes a Dart 3.0+ environment and focuses on applying modern language features to optimize data structures, control flow, and API design.
实现符合Dart惯用风格的代码,利用高级语法(包括模式匹配、records、泛型和健全空安全)来打造健壮、类型安全且简洁的应用。本技能假设使用Dart 3.0+环境,重点在于应用现代语言特性优化数据结构、控制流和API设计。

Instructions

说明

  1. Variable Declaration and Null Safety Apply sound null safety and strict mutability rules when declaring variables.
    • Use
      var
      for local variables with obvious types.
    • Use
      final
      for variables that should not be reassigned.
    • Use
      const
      for compile-time constants.
    • Use
      late
      only when control flow analysis fails to detect initialization, or for expensive lazy initialization.
    • Use wildcard variables
      _
      for non-binding placeholders (requires Dart 3.7+).
    dart
    final name = 'Bob'; // Immutable
    var count = 0; // Obvious type
    late final String expensiveResult = computeExpensiveValue();
    
    // Wildcard usage
    for (var _ in list) {
      print('Iterating without binding');
    }
  2. Function Design and Tear-offs Structure functions using named parameters, optional positional parameters, and tear-offs for concise callbacks.
    • Use
      required
      for mandatory named parameters.
    • Prefer tear-offs over lambdas when passing functions directly.
    dart
    // Named parameters with required and default values
    void configure({required String id, bool verbose = false}) { ... }
    
    // Tear-offs
    final charCodes = [68, 97, 114, 116];
    final buffer = StringBuffer();
    charCodes.forEach(buffer.write); // Method tear-off
  3. Implementing Records for Multiple Returns Use records
    (...)
    to return multiple values without defining a dedicated class.
    dart
    // Returning a record
    (String, int) fetchUserInfo(Map<String, dynamic> json) {
      return (json['name'] as String, json['age'] as int);
    }
    
    // Returning a record with named fields
    ({String name, int age}) fetchNamedUserInfo() {
      return (name: 'Dash', age: 10);
    }
  4. Pattern Matching and Destructuring (Decision Logic) Master pattern matching in assignments, switch statements, and JSON validation. Follow this decision logic when handling complex data:
    • If extracting values from a record or collection: Use variable assignment/declaration patterns.
    • If branching logic based on object shape or type: Use
      switch
      expressions with pattern matching and guard clauses (
      when
      ).
    • If validating external data (e.g., JSON): Use
      if-case
      statements with map/list patterns.
    dart
    // Destructuring a record
    var (name, age) = fetchUserInfo(json);
    
    // Switch expression with algebraic data types and guards
    double calculateArea(Shape shape) => switch (shape) {
      Square(length: final l) when l > 0 => l * l,
      Circle(radius: final r) => math.pi * r * r,
      _ => throw ArgumentError('Invalid shape'),
    };
    
    // JSON Validation using if-case
    if (json case {'user': [String name, int age]}) {
      print('User $name is $age years old.');
    } else {
      // Handle invalid JSON structure
    }
  5. Generics and Type Safety Implement generics
    <T>
    to ensure type safety in reusable components. Apply bounds (
    extends
    ) to restrict parameterized types.
    dart
    // Restricting to non-nullable types
    class Cache<T extends Object> {
      final Map<String, T> _storage = {};
      
      T? getByKey(String key) => _storage[key];
      void setByKey(String key, T value) => _storage[key] = value;
    }
    
    // Generic method
    T first<T>(List<T> items) {
      if (items.isEmpty) throw StateError('No elements');
      return items[0];
    }
  6. Extension Methods and Types Use extension methods and types to add functionality to existing classes or to create zero-cost abstractions over records/types.
    dart
    extension type ButtonItem._(({String label, void Function() onPressed}) _) {
      ButtonItem({required String label, required void Function() onPressed})
          : this._((label: label, onPressed: onPressed));
          
      String get label => _.label;
      void Function() get onPressed => _.onPressed;
    }
  7. Validate and Fix After generating Dart code, verify that:
    • No null dereference errors are possible.
    • Records are used instead of custom classes for simple data tuples.
    • Pattern matching is used for JSON validation instead of verbose
      is
      checks.
    • STOP AND ASK THE USER: If the data structure shape for pattern matching is ambiguous or not provided, pause and ask the user for the expected JSON/Object schema before writing the destructuring logic.
  1. 变量声明与空安全 声明变量时应用健全空安全和严格可变性规则。
    • 对于类型明显的局部变量,使用
      var
    • 对于不应被重新赋值的变量,使用
      final
    • 对于编译时常量,使用
      const
    • 仅当控制流分析无法检测到初始化,或用于代价高昂的延迟初始化时,使用
      late
    • 对于非绑定占位符,使用通配符变量
      _
      (需要Dart 3.7+)。
    dart
    final name = 'Bob'; // 不可变
    var count = 0; // 类型明显
    late final String expensiveResult = computeExpensiveValue();
    
    // 通配符用法
    for (var _ in list) {
      print('Iterating without binding');
    }
  2. 函数设计与方法提取(Tear-offs) 使用命名参数、可选位置参数和方法提取来构建简洁的回调函数。
    • 对于必填命名参数,使用
      required
    • 直接传递函数时,优先使用方法提取而非lambda表达式。
    dart
    // 带有必填参数和默认值的命名参数
    void configure({required String id, bool verbose = false}) { ... }
    
    // 方法提取
    final charCodes = [68, 97, 114, 116];
    final buffer = StringBuffer();
    charCodes.forEach(buffer.write); // 方法提取
  3. 使用Records实现多返回值 使用records
    (...)
    来返回多个值,无需定义专用类。
    dart
    // 返回record
    (String, int) fetchUserInfo(Map<String, dynamic> json) {
      return (json['name'] as String, json['age'] as int);
    }
    
    // 返回带命名字段的record
    ({String name, int age}) fetchNamedUserInfo() {
      return (name: 'Dash', age: 10);
    }
  4. 模式匹配与解构(决策逻辑) 掌握在赋值、switch语句和JSON验证中的模式匹配。处理复杂数据时遵循以下决策逻辑:
    • 如果从record或集合中提取值: 使用变量赋值/声明模式。
    • 如果基于对象形状或类型进行分支逻辑: 使用带有模式匹配和守卫子句(
      when
      )的
      switch
      表达式。
    • 如果验证外部数据(如JSON): 使用带有映射/列表模式的
      if-case
      语句。
    dart
    // 解构record
    var (name, age) = fetchUserInfo(json);
    
    // 带有代数数据类型和守卫的switch表达式
    double calculateArea(Shape shape) => switch (shape) {
      Square(length: final l) when l > 0 => l * l,
      Circle(radius: final r) => math.pi * r * r,
      _ => throw ArgumentError('Invalid shape'),
    };
    
    // 使用if-case进行JSON验证
    if (json case {'user': [String name, int age]}) {
      print('User $name is $age years old.');
    } else {
      // 处理无效JSON结构
    }
  5. 泛型与类型安全 实现泛型
    <T>
    以确保可复用组件的类型安全。应用边界约束(
    extends
    )来限制参数化类型。
    dart
    // 限制为非空类型
    class Cache<T extends Object> {
      final Map<String, T> _storage = {};
      
      T? getByKey(String key) => _storage[key];
      void setByKey(String key, T value) => _storage[key] = value;
    }
    
    // 泛型方法
    T first<T>(List<T> items) {
      if (items.isEmpty) throw StateError('No elements');
      return items[0];
    }
  6. 扩展方法与类型 使用扩展方法和类型为现有类添加功能,或为records/类型创建零开销抽象。
    dart
    extension type ButtonItem._(({String label, void Function() onPressed}) _) {
      ButtonItem({required String label, required void Function() onPressed})
          : this._((label: label, onPressed: onPressed));
          
      String get label => _.label;
      void Function() get onPressed => _.onPressed;
    }
  7. 验证与修复 生成Dart代码后,验证以下内容:
    • 不存在可能的空引用错误。
    • 对于简单数据元组,使用records而非自定义类。
    • 使用模式匹配进行JSON验证,而非冗长的
      is
      检查。
    • 停止并询问用户: 如果模式匹配的数据结构形状不明确或未提供,请暂停并向用户询问预期的JSON/对象架构,再编写解构逻辑。

Constraints

约束条件

  • DO NOT use
    var
    if the assigned type is not immediately obvious to the reader; use explicit types instead.
  • DO NOT use
    dynamic
    unless explicitly interacting with untyped external APIs (and immediately cast/validate it using patterns).
  • DO NOT define a class just to return multiple values from a function; strictly use records.
  • DO NOT use multiple underscores (
    __
    ,
    ___
    ) for unused variables; use the single wildcard
    _
    .
  • DO NOT wrap tear-offs in anonymous functions (e.g., avoid
    list.forEach((e) => print(e))
    ; use
    list.forEach(print)
    ).
  • DO NOT use
    is
    checks and manual casting for JSON validation; strictly use
    if-case
    pattern matching.
  • Related Skills:
    dart-idiomatic-usage
    .
  • 如果赋值的类型对读者而言不明显,请勿使用
    var
    ;请改用显式类型。
  • 除非明确与无类型外部API交互(并立即使用模式进行转换/验证),否则请勿使用
    dynamic
  • 不要仅仅为了从函数返回多个值而定义类;严格使用records。
  • 不要为未使用的变量使用多个下划线(
    __
    ,
    ___
    );请使用单个通配符
    _
  • 不要将方法提取包装在匿名函数中(例如,避免
    list.forEach((e) => print(e))
    ;请使用
    list.forEach(print)
    )。
  • 不要使用
    is
    检查和手动转换进行JSON验证;严格使用
    if-case
    模式匹配。
  • 相关技能:
    dart-idiomatic-usage