美文网首页
dart基础和kotlin不同之处

dart基础和kotlin不同之处

作者: 陆元伟 | 来源:发表于2022-12-07 15:50 被阅读0次

    变量

    声明变量

    声明可以有两种方式,一种是不指定类型,即使用var关键字
    这种发方式和kotlin一样

    var name = 'Bob';
    

    另一种是明确指定类型(Optional types),这种和java一样

    String name = 'Bob';
    

    因为有类型推导,所以两种实现效果一样,官方推荐在函数内的本地变量尽量使用var声明。

    在变量类型并不明确的情况下,可以使用dynamic关键字,这种dynamic和kotlin里的any一样

    dynamic name = 'Bob';
    

    访问限定符

    Dart 没有类似于 Java 那样的 public、protected 和 private 成员访问限定符。如果一个标识符以下划线 (_) 开头则表示该标识符在库内是私有的

    Final 和 Const

    使用过程中从来不会被修改的变量, 可以使用 final 或 const,而不是 var 或者其他类型,Final 变量的值只能被设置一次; Const 变量在编译时就已经固定 (Const 变量 是隐式 Final 的类型) 。最高级 final 变量或类变量在第一次使用时被初始化。

    内建类型

    Dart 语言支持以下内建类型:

    Number
    String
    Boolean
    List (也被称为 Array)
    Map
    Set
    Rune (用于在字符串中表示 Unicode 字符)
    Symbol
    

    后两个kotlin没有,前面几个和kotlin一样

    String

    Dart 字符串是一组 UTF-16 单元序列。 字符串通过单引号或者双引号创建。
    字符串可以通过 ${expression} 的方式内嵌表达式。和kotlin一样。

    使用连续三个单引号或者三个双引号实现多行字符串对象的创建,(和kotlin不一样)

    var s1 = '''
    You can create
    multi-line strings like this one.
    ''';
    

    使用 r 前缀,可以创建 “原始 raw” 字符串:(kotlin没有)

    var s = r"In a raw string, even \n isn't special.";
    

    List,和kotlin一样

      var list = [1, 2, 3];
    

    Set

    var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'};
    var names = {}; // 这样会创建一个 Map ,而不是 Set 。
    

    Map

    和json字符串一样,

    var gifts = {
      // Key:    Value
      'first': 'partridge',
      'second': 'turtledoves',
      'fifth': 'golden rings'
    };
    

    Rune

    在 Dart 中, Rune 用来表示字符串中的 UTF-32 编码字符。
    示 Unicode 编码的常用方法是, \uXXXX, 这里 XXXX 是一个4位的16进制数。 例如,心形符号 (♥) 是 \u2665。 对于特殊的非 4 个数值的情况, 把编码值放到大括号中即可。 例如,emoji 的笑脸 (�) 是 \u{1f600}。

    下面是示例演示了 Rune 、 16-bit code units、 和 32-bit code points 之间的关系。

    main() {
      var clapping = '\u{1f44f}';
      print(clapping);
      print(clapping.codeUnits);
      print(clapping.runes.toList());
    
      Runes input = new Runes(
          '\u2665  \u{1f605}  \u{1f60e}  \u{1f47b}  \u{1f596}  \u{1f44d}');
      print(new String.fromCharCodes(input));
    }
    

    Symbol

    一个 Symbol 对象表示 Dart 程序中声明的运算符或者标识符
    通过字面量 Symbol ,也就是标识符前面添加一个 # 号,来获取标识符的 Symbol 。

    #radix
    #bar
    

    函数

    可选参数

    可选参数可以是命名参数或者位置参数,但一个参数只能选择其中一种方式修饰。
    命名可选参数

    调用函数时,可以使用指定命名参数 paramName: value。 例如:

    enableFlags(bold: true, hidden: false);
    

    定义函数是,使用 {param1, param2, …} 来指定命名参数:

    /// Sets the [bold] and [hidden] flags ...
    void enableFlags({bool bold, bool hidden}) {...}
    

    使用 @required 注释表示参数是 required 性质的命名参数,required参数调用时必须要传, 该方式可以在任何 Dart 代码中使用(不仅仅是Flutter)。

    const Scrollbar({Key key, @required Widget child})
    

    位置可选参数

    将参数放到 [] 中来标记参数是可选的:

    String say(String from, String msg, [String device]) {
      var result = '$from says $msg';
      if (device != null) {
        result = '$result with a $device';
      }
      return result;
    }
    

    默认参数值

    在定义方法的时候,可以使用 = 来定义可选参数的默认值。 默认值只能是编译时常量。 如果没有提供默认值,则默认值为 null。

    下面是设置可选参数默认值示例:

    /// 设置 [bold] 和 [hidden] 标志 ...
    void enableFlags({bool bold = false, bool hidden = false}) {...}
    
    // bold 值为 true; hidden 值为 false.
    enableFlags(bold: true);
    

    函数是一等对象

    一个函数可以作为另一个函数的参数。 例如:
    
    void printElement(int element) {
      print(element);
    }
    
    var list = [1, 2, 3];
    
    // 将 printElement 函数作为参数传递。
    list.forEach(printElement);
    

    词法闭包

    闭包 即一个函数对象,即使函数对象的调用在它原始作用域之外, 依然能够访问在它词法作用域内的变量。
    函数可以封闭定义到它作用域内的变量。 接下来的示例中, makeAdder() 捕获了变量 addBy。 无论在什么时候执行返回函数,函数都会使用捕获的 addBy 变量。

    /// 返回一个函数,返回的函数参数与 [addBy] 相加。
    Function makeAdder(num addBy) {
     return (num i) => addBy + i;
    }
    
    void main() {
     // 创建一个加 2 的函数。
     var add2 = makeAdder(2);
    
     // 创建一个加 4 的函数。
     var add4 = makeAdder(4);
    
     assert(add2(3) == 5);
     assert(add4(3) == 7);
    }
    

    级联运算符 (..)(kotlin没有)

    级联运算符 (..) 可以实现对同一个对像进行一系列的操作。 除了调用函数, 还可以访问同一对象上的字段属性。 这通常可以节省创建临时变量的步骤, 同时编写出更流畅的代码。

    考虑一下代码:

    querySelector('#confirm') // 获取对象。
      ..text = 'Confirm' // 调用成员变量。
      ..classes.add('important')
      ..onClick.listen((e) => window.alert('Confirmed!'));
    

    第一句调用函数 querySelector() , 返回获取到的对象。 获取的对象依次执行级联运算符后面的代码, 代码执行后的返回值会被忽略。

    上面的代码等价于:

    var button = querySelector('#confirm');
    button.text = 'Confirm';
    button.classes.add('important');
    button.onClick.listen((e) => window.alert('Confirmed!'));
    

    级联运算符可以嵌套,例如:

    final addressBook = (AddressBookBuilder()
          ..name = 'jenny'
          ..email = 'jenny@example.com'
          ..phone = (PhoneNumberBuilder()
                ..number = '415-555-0100'
                ..label = 'home')
              .build())
        .build();
    
    

    赋值运算符??=

    使用 = 为变量赋值。 使用 ??= 运算符时,只有当被赋值的变量为 null 时才会赋值给它。

    // 将值赋值给变量a
    a = value;
    // 如果b为空时,将变量赋值给b,否则,b的值保持不变。
    b ??= value;
    
    

    类型判定运算符

    as, is, 和 is! 运算符用于在运行时处理类型检查

    异常

    catch

    捕获异常可以避免异常继续传递(除非重新抛出( rethrow )异常)。 可以通过捕获异常的机会来处理该异常:

    try {
      breedMoreLlamas();
    } on OutOfLlamasException {
      // 一个特殊的异常
      buyMoreLlamas();
    } on Exception catch (e) {
      // 其他任何异常
      print('Unknown exception: $e');
    } catch (e) {
      // 没有指定的类型,处理所有异常
      print('Something really unknown: $e');
    }
    

    捕获语句中可以同时使用 on 和 catch ,也可以单独分开使用。 使用 on 来指定异常类型, 使用 catch 来 捕获异常对象。

    catch() 函数可以指定1到2个参数, 第一个参数为抛出的异常对象, 第二个为堆栈信息

    try {
      // ···
    } on Exception catch (e) {
      print('Exception details:\n $e');
    } catch (e, s) {
      print('Exception details:\n $e');
      print('Stack trace:\n $s');
    }
    

    finally

    不管是否抛出异常, finally 中的代码都会被执行。 如果 catch 没有匹配到异常, 异常会在 finally 执行完成后,再次被抛出:

    对象

    构造函数

    class Point {
      num x, y;
    
      // 在构造函数体执行前,
      // 语法糖已经设置了变量 x 和 y。
      Point(this.x, this.y);
    }
    

    命名构造函数

    使用命名构造函数可为一个类实现多个构造函数, 也可以使用命名构造函数来更清晰的表明函数意图

    class Point {
      num x, y;
    
      Point(this.x, this.y);
    
      // 命名构造函数
      Point.origin() {
        x = 0;
        y = 0;
      }
    }
    

    初始化列表

    除了调用超类构造函数之外, 还可以在构造函数体执行之前初始化实例变量。 各参数的初始化用逗号分隔。

    // 在构造函数体执行之前,
    // 通过初始列表设置实例变量。
    Point.fromJson(Map<String, num> json)
        : x = json['x'],
          y = json['y'] {
      print('In Point.fromJson(): ($x, $y)');
    }
    

    重定向构造函数

    有时构造函数的唯一目的是重定向到同一个类中的另一个构造函数。 重定向构造函数的函数体为空, 构造函数的调用在冒号 (:) 之后.
    和kotlin的扩展方法写法类型

    class Point {
      num x, y;
    
      // 类的主构造函数。
      Point(this.x, this.y);
    
      // 指向主构造函数
      Point.alongXAxis(num x) : this(x, 0);
    }
    

    常量构造函数

    如果该类生成的对象是固定不变的, 那么就可以把这些对象定义为编译时常量。 为此,需要定义一个 const 构造函数, 并且声明所有实例变量为 final。

    class ImmutablePoint {
      static final ImmutablePoint origin =
          const ImmutablePoint(0, 0);
    
      final num x, y;
    
      const ImmutablePoint(this.x, this.y);
    }
    

    工厂构造函数

    当执行构造函数并不总是创建这个类的一个新实例时,则使用 factory 关键字。 例如,一个工厂构造函数可能会返回一个 cache 中的实例, 或者可能返回一个子类的实例。

    以下示例演示了从缓存中返回对象的工厂构造函数

    class Logger {
      final String name;
      bool mute = false;
    
      // 从命名的 _ 可以知,
      // _cache 是私有属性。
      static final Map<String, Logger> _cache =
          <String, Logger>{};
    
      factory Logger(String name) {
        if (_cache.containsKey(name)) {
          return _cache[name];
        } else {
          final logger = Logger._internal(name);
          _cache[name] = logger;
          return logger;
        }
      }
    
      Logger._internal(this.name);
    
      void log(String msg) {
        if (!mute) print(msg);
      }
    }
    

    为类添加功能: Mixin

    Mixin 是复用类代码的一种途径, 复用的类可以在不同层级,之间可以不存在继承关系。

    通过 with 后面跟一个或多个混入的名称,来 使用 Mixin , 下面的示例演示了两个使用 Mixin 的类

    class Musician extends Performer with Musical {
    // ···
    }
    
    class Maestro extends Person
      with Musical, Aggressive, Demented {
    Maestro(String maestroName) {
      name = maestroName;
      canConduct = true;
    }
    }
    

    过创建一个继承自 Object 且没有构造函数的类,来 实现 一个 Mixin 。 如果 Mixin 不希望作为常规类被使用,使用关键字 mixin 替换 class

    mixin Musical {
      bool canPlayPiano = false;
      bool canCompose = false;
      bool canConduct = false;
    
      void entertainMe() {}
    

    相关文章

      网友评论

          本文标题:dart基础和kotlin不同之处

          本文链接:https://www.haomeiwen.com/subject/ixpkartx.html