美文网首页
Learn Dart Based on Java

Learn Dart Based on Java

作者: 奋飞的蜗牛ing | 来源:发表于2018-10-26 20:47 被阅读113次

    在Java的基础上快速学习Dart语言,快速进入Flutter项目开发。

    • 例1:操作符

    ~/ 整除
    b ??= value // b为null,才进行赋值操作
    person?.age = 33 // If p is non-null, set its age value to 33
    print(person?.age) // person不为null时返回age值,否则返回null
    
    String playerName(String name) => name ?? 'Guest'; 
    等价于:
    String playerName(String name) => name != null ? name : 'Guest';
    
    instanceof 替换为 is;
    as 类型转换(t as Person).name
    
    • 例2:数据类型

    num get area => pi * pow(radius, 2); // num可以用double,dart推荐使用num
    int lineCount; // lineCount默认赋值null,dart中一切都是objects;
    int 是一个对象类型;
    int、double属于num,dart推荐使用num;

    • 例3:工厂模式的两种方法

    第一种:新建一个工厂类
    Shape shapeFactory(String type) {
      if (type == 'circle') return Circle(2);
      if (type == 'square') return Square(2);
      throw 'Can\'t create $type.';
    }
    第二种:使用dart中关键字factory,在基类中构造函数中进行处理。
    abstract class Shape {
      factory Shape(String type) {
        if (type == 'circle') return Circle(2);
        if (type == 'square') return Square(2);
        throw 'Can\'t create $type.';
      }
      num get area; // 抽象方法
    }
    

    Dart 中 Factory 构造函数作用:不用总是创建新的对象,可以返回已缓存的对象,也可以返回一个子类对象。【工厂模式】

    class Logger {
      final String name;
      bool mute = false;
      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);
      }
    }
    
    • 例4:Object等价于dynamic

    var name = 'Bob'; // dart推荐
    dynamic name = 'Bob';
    String name = 'Bob';
    
    • 例5:final与const的区别

    final 要求变量只能初始化一次,并不要求赋的值一定是编译时常量,可以是常量也可以不是。而 const 要求在声明时初始化,并且赋值必需为编译时常量。final 是惰性初始化,即在运行时第一次使用前才初始化。而 const 是在编译时就确定值了。

    定义形式:
    var a = 1;
    const a = 1;
    final a = 1;
    int a = 1;
    const int a = 1;
    final int a = 1;
    

    错误区别:
    var aa = const [1, 2, 3];
    final bb = [1, 2, 3];
    aa=const [11, 22, 33];
    //bb=const [11, 22, 33]; // 错误,bb不能修改
    //aa[1]=77; // 错误,aa中的内容不能修改
    bb[1]=77;
    
    • 例6:类型转换

    var one = int.parse('1'); // 可见int是个对象
    var onePointOne = double.parse('1.1'); // 可见double是个对象
    String oneAsString = 1.toString(); // int -> String
    
    • 例7:函数

    bool isNoble(a) { // bool可以省略;a可以不用指定类型
      return a != null; // 所有函数默认返回null
    }
    
    • 可选参数 { } [ ]
      { }调用时需要加上别名
      [ ]调用时是按照顺序
    • 默认参数
      void func({bool bold = false, bool hidden = false}) {...}
    • 函数可以作为参数进行传递

    String scream(String str) => "num is "+str;
    main() {
      final values = [1, 2, 3, 5, 10, 50];
      for (var length in values) {
        print(scream(length));
      }
    }
    for循环代替为:
      values.map(scream).forEach(print);
      values.skip(1).take(3).map(scream).forEach(print); // skip从0开始
    
    void printElement(int element) {
      print(element);
    }
    var list = [1, 2, 3];
    list.forEach(printElement);
    
    • 匿名函数

    var list = ['apples', 'bananas', 'oranges'];
    list.forEach(**(item)** { // 构建匿名函数
      print('\${list.indexOf(item)}: \$item');
    });
    
    var loudify = (msg) => '!!!\ ${msg.toUpperCase()} !!!'; // 构建匿名函数
    print(loudify('hello'));
    
    • 函数嵌套

    makeAdder(num addBy) {
      return (num i) => addBy + i; // 返回一个匿名函数
    }
    
    void main() {
      var add4 = makeAdder(4);
      print(makeAdder(2)(3) == 5);
      print(add4(3) == 7);
    }
    
    • 例8:类

    dart支持抽象类;并且可以在一个文件中定义多个类。

    class Bicycle {
      int cadence;
      int _speed; // 下划线表示私有
      int get speed => _speed; // get方法
      int gear;
    Bicycle(this.cadence, this.speed, this.gear); // 简化构造函数,不要忘记尾部分号
    // 单引号,双引号一样;'''  '''输出多行;var s = r'C://a/b/'(r表示raw)
    // ${expression} 表达式
    // $variableName 标识符
    // => 一行函数或方法
    @override
    String toString() => 'Bicycle: $speed mph';
    
    // 不能写return   getGear() => return gear;
    getGear() => gear;
    }
    void main() {
    // 可以省略new
      var bike = new Bicycle(2, 0, 1);
      print(bike); // Instance of 'Bicycle'
    }
    
    • constant constructors

    var a = const ImmutablePoint(1, 1);
    var b = const ImmutablePoint(1, 1); // a b are the same instance
    var c = ImmutablePoint(1, 1); // a c are not the same instance
    

    const构造函数得到的类不能够再改变。

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

    class Point {
      num x, y;
      Point(this.x, this.y); // 构造函数:Dart has syntactic sugar to make it easy
    
      // Named constructor
      Point.origin() {
        x = 0;
        y = 0;
      }
    }
    
    • Named constructor 手动调用父类有参构造函数

    class Person {
      String firstName;
      Person.fromJson(Map data) {
        print('in Person');
      }
    }
    
    class Employee extends Person {
      // Person does not have a default constructor;
      // you must call super.fromJson(data).
      Employee.fromJson(Map data) : super.fromJson(data) {
        print('in Employee');
      }
    } // Warning: The right-hand side of an initializer does not have access to this.
    
    main() {
      var emp = new Employee.fromJson({});
      if (emp is Person) {
        emp.firstName = 'Bob';
      }
      (emp as Person).firstName = 'Bob';
    }
    

    Warning: The right-hand side of an initializer does not have access to this.

    • Named constructor 使用已有构造函数

    class Point {
      num x, y;
      Point(this.x, this.y);
      Point.alongXAxis(num x) : this(x, 0); // // 不能访问this属性,但可以调用已有构造函数
    }
    
    • get set方法的简化

    class Rectangle {
      num left, top, width, height;
      Rectangle(this.left, this.top, this.width, this.height);
      // Define two calculated properties: right and bottom.
      num get right => left + width;
      set right(num value) => left = value - width;
      num get bottom => top + height;
      set bottom(num value) => top = value - height;
    }
    
    void main() {
      var rect = Rectangle(3, 4, 20, 15);
      assert(rect.left == 3);
      rect.right = 12; // 调用set right方法
      assert(rect.left == -8);
    }
    
    • implements

    Dart中有抽象类,关键字:abstract。
    dart没有interface关键字,因为所有的类都定义成了interface,类都是隐式接口。
    隐式的接口:每一个类都隐式的定义一个接口,这个接口包含了这个类的所有实例成员和它实现的所有接口。如果相应创建一个类A, 这个类A 支持类B 提供的API函数,但是不继承B 的实现,则类A 需要实现类B 的接口。

    class Imposter implements Person, PersonB {
    // Person是一个类,实现Person类的所有属性成员和方法。
    // 可以“多实现”
    }
    
    • 例9:重载操作符

    Dart可以重载操作符【!=不可以进行重载;若重载了==,必须同时重载hashCode】

    class Vector {
      final int x, y;
      Vector(this.x, this.y);
      Vector **operator** +(Vector v) => Vector(x + v.x, y + v.y);
      Vector **operator** -(Vector v) => Vector(x - v.x, y - v.y);
    }
    
    • 例10:枚举

    每个枚举类型都用于一个index的getter,用来标记元素的元素位置。第一个枚举元素的标是0 。

    enum Color { red, green, blue }
    assert(Color.red.index == 0);
    assert(Color.blue.index == 2);
    values获取所有枚举值:
    List<Color> colors = Color.values;
    assert(colors[2] == Color.blue);
    
    • 例11:mixins混合类型使用关键字with

    Mixins不是一种在经典意义上获得多重继承的方法。Mixins是一种抽象和重用一系列操作和状态的方法。它类似于扩展类所获得的重用,但它与单继承兼容,因为它是线性的。

    class T = A with S; // A中的方法为A和S方法的集合,如果有重复,取S中的。
    class T = B with A, S 等价于 class T = (B with A) with S;
    

    注:使用Mixin时必须继承至Object,并且不能调用super()方法。
    mixins比较陌生,也比较重要。详细资料参考:
    https://juejin.im/post/5bb204d3e51d450e4f38e2f6

    • 例12:泛型

    abstract class Cache<T> {
      T getByKey(String key);
      void setByKey(String key, T value);
    }
    var names = <String>['Seth', 'Kathy', 'Lars'];
    var pages = <String, String>{
      'index.html': 'Homepage',
    };
    

    print(names is List<String>); // true
    由于Java在运行时会删除掉泛型,所以在Java中只能判读names是否为List,而不能判断是否为List<String>。
    var views = Map<int, View>(); // int也是对象
    class Foo<T extends SomeBaseClass> { }
    泛型方法:T first<T>(List<T> ts) {

    • 例13:Cascade ..

    Cascade notation (..) Dart 支持使用两个点号(..)进行级联调用(cascade operator),级联调用和普通方法调用一样,但是它并不返回方法的返回值,而是返回调用对象自身,这样你就可以连续调用同一个对象上的多个方法了。

    Cascade ..例子:
    var button = querySelector('#confirm');
    button.text = 'Confirm';
    button.classes.add('important');
    button.onClick.listen((e) => window.alert('Confirmed!'));
    等价于:
    querySelector('#confirm') // Get an object 没有分号
      ..text = 'Confirm'
      ..classes.add('important')
      ..onClick.listen((e) => window.alert('Confirmed!'));
    
    • 例14:异常Exception和Error

    try {
      breedMoreLlamas();
    } on OutOfLlamasException {
      // A specific exception
      buyMoreLlamas();
    } on Exception catch (e) {
      // Anything else that is an exception
      print('Unknown exception: $e');
      **rethrow;**
    } catch (e, s) {
      // No specified type, handles all
      print('Something really unknown: $e');
    }
    
    • 例15:import

    import 'package:lib2/lib2.dart' **as** lib2;
    // Import only foo.
    import 'package:lib1/lib1.dart' show foo;
    // Import all names EXCEPT foo.
    import 'package:lib2/lib2.dart' hide foo;
    // To lazily load a library 延迟加载
    import 'package:greetings/hello.dart' **deferred as** hello;
    
    • 例16:异步

    Future greet() async { // 必须返回Future,必须有async,await
      await hello.loadLibrary();
      hello.printGreeting();
    }
    
    Future<String> lookUpVersion() async => '1.0.0'; // dart会自动添加await
    

    返回Future时,dart会自定添加为:Future<void>;
    处理流数据使用await for.

    • 例17:生成器 yield

    • 同步生成器:使用sync*和yield
    Iterable<int> naturalsTo(int n) sync* {
      int k = 0;
      while (k < n) yield k++;
    }
    
    • 异步成器:使用async*和yield
    Stream<int> asynchronousNaturalsTo(int n) async* {
      int k = 0;
      while (k < n) yield k++;
    }
    
    • 递归生成器 使用yield*
    Iterable<int> naturalsDownFrom(int n) sync* {
      if (n > 0) {
        yield n;
        yield* naturalsDownFrom(n - 1);
      }
    }
    
    • 例18:Typedefs定义函数

    dart中函数也是对象,使用Typedefs定义函数类型。

    typedef Compare = int Function(Object a, Object b);
    class SortedCollection {
      Compare compare;
      SortedCollection(this.compare);
    }
    // Initial, broken implementation.
    int sort(Object a, Object b) => 0;
    void main() {
      SortedCollection coll = SortedCollection(sort);
      assert(coll.compare is Function); // OK
      assert(coll.compare is Compare); // OK
    }
    
    • 例19:元数据@

    library todo;
    class Todo {
      final String who;
      final String what;
      const Todo(this.who, this.what);
    }
    使用:
    @Todo('seth', 'make this do something')
    void doSomething() {
      print('do something');
    }
    
    • 例20:其它

    Map中的key和value支持任何数据类型:

    Maps:Both keys and values can be any type of object
    var gifts = {
      'first': 'partridge',
      10: 'neon', // key可以为num类型
    };
    

    main()入口的两种表达方式:

    void main() { }
    void main(List<String> arguments) { } // 命令行执行携带参数
    

    运行时类型获取 runtimeType:

    print('The type of a is ${a.runtimeType}');
    

    assert的一个使用场景:

    Point.withAssert(this.x, this.y) : assert(x >= 0) {
      print('In Point.withAssert(): ($x, $y)');
    }
    
    • 总结

    该文章只是参考Dart官网文档,在Java的基础上,简单的介绍了一下Dart基本语法。以后会对Dart Library进行一些实用性的介绍。

    相关文章

      网友评论

          本文标题:Learn Dart Based on Java

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