从Swift学习Dart

93 阅读3分钟
  1. Learning Dart as a Swift Developer

Swift vs Dart

  • 相同特性

  • Dart特有

    • Mixins,和Swift一样支持预先编译AOT(Ahead-Of-Time)compilation,同时也支持JIT(Just-In-Time)compilation模式,可以增量编译和debug

Lint:静态解析

拓展阅读:Customizing static analysisdart fix解析修复、IDE的Dart Format、Effective Dart and Linter rules.

变量Variables

final = let, var =var(支持类型推断)

const常量定义、const 数据定义

const bar = 100; // 常量 constant variables
// in class 使用 static const
class StandardAtmosphere {
    static const bar = 100;
    static const double atm = 1.0 * bar; // 
}
final name =  'Bob'; // immutable 仅设置一次 相当于 let name = "Bob"

// final 和 const区别
final foo1 = const [1, 2, 3]; 
const foo2 = [1, 2, 3];
const bar2 = foo2; // oK
const bar1 = foo1; // Compile-time Error!!!

内建类型

拓展阅读: Built-in types

  • 基础数据类型

    • Numbers(num、int、double)
    • int intVariable = 3;
      double doubleVariable = 3.0;
      print(intVariable == doubleVariable); // true
      
    •   拓展阅读:Numbers in Dart
    • String(String)
    • final singleQuotes = 'T'm learning Dart';
      final unicode = '\u{1F60E}'; //😎,  Unicode scalar U+1F60E
      var food = 'bread';
      var str = 'I eat $food';
      var str1 = 'I eat ${bakery.bestSeller}';
      
      // 和 Swift一样支持"""
      final str2 = """ 
          123
          456
          789""";
      // Raw String 和Swift.# = Dart=.r
      // Swift: let str3 = #"name1 \n name2"#
      final str3 = r""" 
          123
          456 \n
          789""";
      var str4 = "name".toUpperCase; // NAME
      
    •   拓展阅读:Runes and grapheme clusters
    • Booleans(bool)
  • 集合数据类型

    • 数组List/Array(List)
    • 集合Set(Set)
    • 字典Map/Dictionary(Map)
  • 可选类型

a ??= b; // a = a ?? b

非空,用时初始化标识

未初始化,先用,则会出发运行时错误!

使用场景之一:lazy load懒加载

class Weather {
    late int _temperature = _readThermometer();
}

函数Function

  • Main
void main() {
    // main function is the entry point
    print('hello world');
}

不支持元组Tuples?但是:several tuple packages

Error:平常指的是程序错误或系统级别的failures失败,不必捕捉的

Exception:平常是指可以恢复的failure失败,想要被cathc捕捉到的

  • Try-catch
try {
    // Create audio player object
    audioPlayer = AVAudioPlayer(soundUrl);
    // play the sound
    audioPlayer.play();
}
catch {
    // couldn't create the player for file,log the exception
    print('couldn't create the player for file $soundFileName,log the exception');
}

拓展阅读:exceptions and errors.

// 设置默认值a,b Positional Parameter;c,d Named Parameter { 内的定义 }
int multiply(int a, int b, {int c = 1, int d = 1}) {
     return a * b * c * d;
}

multiply(23);
multiply(2, 3, c: 2);

int multiply(int a, { required int b }){
    return a * b;
}
multiply(2, b: 3);

// 注意:可选占位参数必须在required 之后,不能和Named Parameter混用
// 可选Positional Parameter
int multiply(int a, int b, [int c = 1, int d = 1]){
    return a * b * c * d;
}
multiply(1, 2);
multiply(1, 2, 3, 4);
// 函数可以作为参数、返回值使用
typedef int MultiplyFunction(int value);
MultiplyFunction multiplyBy(int multiplier) {
    return (int value) {
        return value * multiplier;
    }
}
MultiplyFuntion funcByTwo = multiplyBy(2);
// call
print(funcByTwo(3)); // 6
  • 匿名函数 Anonymous Funtion= Swift的闭包

    • 创建方式
// 方式一
// map return Interable<T> 而不是List<T>所有要使用toList()
[1, 2, 3].map((elment) {
    return element * 2;
}).toList(); // [2, 4, 6]

// 单行 实现
[1, 2, 3].map ((element) =>  element * 2).toList();

// 普通函数也适用
multipy(int a, int b) => a * b;
int multipy(int a, int b) {
    return a * b
}

同步函数生成器-Iterable

// 同步函数生成器
Iterable<int> listNumbers(int n) sync* {
    int k = 0;
    while (k < n) yield k++;
}
// Returns an `Iterable<int>` that iterates
// through 0, 1, 2, 3, and 4.
print(listNumbers(5));

Iterable<int> doubleNumbersTo(int n) sync* {
    int k = 0;
    while (k < n) {
        yield* [k, k];
        k++;
    }
}
// Returns an iterable with [0, 0], [1, 1], and [2, 2].
print(doubleNumbersTo(3));

异步函数生成器使用-streams,拓展阅读:Concurrency

Statements声明

  • 控制流

    • if-else
var a = 1;
if (a == 1) {
    a = 1;
} else if (a == 2) {
    a = 2;
} else {
    a = 3;
}
if (a == 1) a = 1;
print(a);

条件判断加了()

  • For-in
// 数组遍历
var list = [0, 1, 2];
for (var i in list) {
    print(i);
}

// Map 遍历没有 for- in;使用Map.forEach
Map<String, int> dict = {
    'Foo': 1,
    'Bar': 2
}

for (var e in dict.entries) {
    print('${e.key}, ${e.value}');
}
dict.forEach((key, value)) {
    print('$key, $value');
});
class Vector {
    final double x;
    final double y;
    final double z;
    
    Vector operator +(Vector v) {
        return Vector(x: x + v.x, y: y + v.y, z: z + v.z);
    }
}

Swift可以自定义运算符

  • 算数运算符
assert(2 + 3 == 5);
assert(2 - 3 == -1);
assert(2 * 3 == 6);
assert(5 / 2 == 2.5); // Result is a double
assert(5 ~/ 2 == 2); // Result is an int
assert(5 % 2 == 1); // Remainder
a = 0;
b = ++a; // Increment a before b gets its value.
assert(a == b); // 1 == 1
a = 0;
b = a++; // Increment a AFTER b gets its value.
assert(a != b); // 1 != 0

web和native可能有所不同,~/ 是floor(截取) 和 而不是round(向上取整)

var person = Employee();
var person1 = Persion();

(person as Employee).employeeNumber = 123;
if (person1 is! Employee) print('Not Employee');
if (person1 is Person) {        
     print(' A Person');
     person1.name = 'Bob'; // 可以使用name属性了
}

拓展阅读:see Bitwise operations in the Numbers in Dart page.

  • 位运算符
final value = 0x22;
final bitmask = 0x0f;

assert((value & bitmask) == 0x02); // AND
assert((value & ~bitmask) == 0x20); // AND NOT
assert((value | bitmask) == 0x2f); // OR
assert((value ^ bitmask) == 0x2d); // XOR
assert((value << 4) == 0x220); // Shift left
assert((value >> 4) == 0x02); // Shift right
// Result may differ on the web 
assert((-value >> 4) == -0x03); // Shift right 

跨平台使用 可能结果不同,详见 Bitwise operations

  • Cascades(.. 操作符)
Animal animal = Animal()
    ..name = 'Bob'
    ..age = 5
    ..feed()
    ..walk();
print(animal.name); // Bob
print(animal.age)l // 5

Collections集合

final List<String> list1 = <String>['one', 'two', 'three'];
final list2 = <String>['one', 'two', 'three'];
final list3 = ['one', 'two', 'three'];

final string = list1[1];
list1.add('four');
list1.addAll(['five', 'six']);

不可变数组

// 1. 编译时常量数组
const list3 = ['one', 'two', 'three'];

// 2. final 不可更改为其他的list,但可以增/删元素个数
final list4 = ['one', 'two', 'three'];

// 3. 不可更改数组元素个数
final list5 = List<String>.unmodifiable['one', 'two', 'three'];

展开操作符Spread Operators(...)

final list = [1, 2];
final list1 = [0, ...list]; // [0, 1, 3]

List<int>? list;
// Swift: let list2 = [0] + list ?? []
final list2 = [0, ...?list]; // [0] 
// Swift Dictionary Key的类型 KeyType:Hashable
final gifts = {'first': 'partridge','second': 'turtle doves','fifth': 'golden rings',};
final nobleGases = {2: 'helium',10: 'neon',18: 'argon',};

final gift = gifts['first']; // ‘partridge'

assert(gifts.containsKey('fifth')); // false
gifts['third'] = 'turtle'; // Gets added
gifts['second'] = 'turtle doves'; // Gets updated
gifts.remove('first');
gifts.removeWhere((key, value) => value == 'partridge');

Dart hashCode集成子Object类, hashCode property

// Swift: var abc: Set<String> = ["a", "b"]; // String: Hashable
final abc = {'a', 'b', 'c'}; 
final abc = Set<String>.unmodifiable(['a', 'b', 'c']);

Classes

不支持值类型,所以没有Struct

Enums枚举类型,Dart2.17增强了枚举类型的使用,支持继承、设置state和添加方法

拓展阅读: Declaring enhanced enums

  • Constructors构造函数
// 标准构造函数,new不建议使用了
class Point {
    double x = 0;
    double y = 0;
    Point(double x, double y) {
        this.x = x;
        this.y = y;
    }
}

Point p = Point(2, 1.0);

// 构造函数,语法糖
class Point {
    double x = 0;
    double y = 0;
    Point(this.x, this.y);
    // With an optional positioned parameter
    Point(this.x, [this.y = 0]);
     // With named parameters
     Point({required this.y, this.x = 0});
     // With both positional and named parameters
     Point(int x, int y, {int scale = 1}) {...}
     
     // Delegates to the main constructor.
     Point.alongXAxis(double x) : this(x, 0);

}

Initializer lists

class Point {
    double x = 0;
    double y = 0;
    // 常量类型构造器
    const Point(this.x, this.y);
    // Named Constructor
    Point(Map<String, double> json)
        : x = json['x']!,
           y = json['y']! {
           
         print('Point = ($x, $y)');
     }
}

工厂构造器,使用场景如:返回缓存的对象

class Logger {
    static final Map<String, Logger> _cache = <String, Logger>{}
    // Factory constructor that returns a cahched copy,
    // or creates a new one if it's not yet availabe
    factory Logger(String name) => _cache[name] ??= Logger._internal(name);
    Logger._internal(this.name);
}

Getter & Setter

class Rectangle {
    double left, top, width, height;
    Rectangle(this.left, this.right, this.width, this.height);
    
    // 计算属性
    double get right => width + left;
    set right(double value) => width = value - left;
    
    double get bottom => top + height;
    set bottom(double value) => height = value - top;
}
  • 抽象类实现

拓展阅读: abstract classes, implicit interfaces, and extending a class sections

abstract class AbstractContainer {
    void updateChildren();
    
    String toString() => "AbstractContainer";
}

abstract class Animal {
    int getLegs();
    void makeNoise();
}

class Dog implements Animal {
    @override
    int getLegs() => 4;
    @override
    void makeNoise() => print('Woof Woof!!!');
}

// 或者
class Dog extends Animal {
    // ...
}
  • Mixin 混合
abstract class Animal {}
// Defining the mixins
mixin Flyer {fly() => print('Flaps wings');}
mixin Walker {walk() => print('Walks legs');}
class Bat extends Animal with Flyer {}
class Goose extends Animal with Flyer, Walker {}
class Dog extends Animal with Walker {}

// Correct calls
Bat().fly();
Goose().fly();
Goose().walk(); 
Dog().walk();

// Incorrect calls
Bat().walk(); // Not using the Walker mixin
Dog().fly(); // Not using the Flyer mixin
class Animal {
}

方法响应栈

// Bird > Flyer > Consumer > Animal
class Bird extends Animal with Consumer, Flyer {}
  • Extension扩展
extension NumberParsing on String {
    int parseInt() {
        return int.parse(this);
        }
}

print('21'.parseInt() * 2); // 42

作用域

// Hide "MyExtension" when importing types from
// "path/to/file.dart".
import 'path/to/file.dart' hide MyExtension; 
// Only show "MyExtension" when importing types
// from "path/to/file.dart".
import 'path/to/file.dart' show MyExtension;
// The `shout()` method is only available within this 
library.extension _Private on String {
    String shout() => this.toUpperCase();
}

// 扩展中不能直接添加初始化方法,但是仍可返回类对象
extension SomePerson on Person {
    static Person create(String firstName, String lastName) {
        return Person(firstName, lastName);
    }
}
  • Override 重写
class SomePerson implements Person {
    @override 
    void walk() => print('somebody walk');
}

TODO

Generics

Concurrency

Doc Comments

Libraries and visibility

  1. Flutter concurrency for Swift developers.

  1. Dart overview

语法层面

语言特性:连贯、简洁(语法层面的特性,一致性、高效、健壮编程)

核心库(丰富的跨平台库,高效编程)

如集合对象的(dart:collection),数学计算的 (dart:math), 编解码数据解析(dart:convert), 其他的commonly used packages

  • 跨平台的库
  • 原生库
  • Web库

包管理(创建包、依赖管理)

项目开发(IDE、Debug、静态代码分析、测试等)

底层原理

  1. Dart编译流程

  2. Dart Analyzer