Dart十大特性速记

603 阅读1分钟

大家好,我是言淦,我今天带来的文章是《Dart十大特性速记》, 编程语言总是朝着轻便化前进, Dart也不例外,下面的内容来自官方文档以及自己的一些想法,希望能给你们带来帮助!

环境: Dart VM version: 2.3.0-dev.0.1

参考: dart.dev/codelabs/da…

注: 本文所说的构造器等同于构造函数!

1.字符串插值(字符串运算+替换)

print('${3 + 2}')  // '5'
print('${"word".toUpperCase()}')  // 'WORD'
print('$myObject')  // The value of myObject.toString()

2. ?? 和 ??= 运算符

”a ??= b“: 先判断变量 a 是否为 null,如果为 null 则将b的值赋予a,否则跳过; 
”a ?? b“ 这里的a和b针对的是表达式, 当表达式a不为null, 返回a; 如果a为null, 返回b。其实 ?? 和 ??= 差不多, 只不过 ?? 第一个值为表达式,而 ??= 第一个值为变量。
“a ? b :c” 三元表达式
“?.” : 看下面的例子

int a; // Dart变量初始值为null,不为0或者其他值
a ??= 3;
print(a); // 3.

a ??= 5;
print(a); // a 的值仍然为 3.

print(1 ?? 3); // 打印 1.
print(null ?? 12); // 打印 12.

myObject?.someProperty   
等价于
(myObject != null) ? myObject.someProperty : null

3.箭头函数(=>)

当函数的返回语句只有一句时,可以用箭头函数代替,算是 Dart 里面最常用的了

void main() {
  void helloWorld() => print("hello world");
  helloWorld();

  /*
    等价于
    void helloWorld() {
      print("hello world");
    }
  
  */
}

4.级联器(..)

class Rectangle {
  int width;
  int height;
  // 等价于 int area() => width * height;
  int area() {
    return this.width * this.height;
  }
}

void main() {
  // 初始化一个对象
  Rectangle r = Rectangle()
  ..width = 10
  ..height = 20;

  /*
    等价于
    Rectangle r = Rectangle();
    r.width = 10;
    r.height = 20;  
  */

  print(r.area());  // 200
  print(r..area()); // Instance of 'Rectangle'

  // 看不到东西,但实际上执行了area函数
  Rectangle()
  ..width = 20
  ..height = 20
  ..area();
}

5.getter 和 setter选择器

class MyClass {
  int _aProperty = 0;
  
  int get aProperty => _aProperty;
  
  set aProperty(int value) {
    if (value >= 0) {
      _aProperty = value;
    }
  }
}

等价于

class MyClass2 {
  int _aProperty = 0;

  int getAProperty() {
    return _aProperty;
  }

  void setAProperty(int value) {
    if (value >= 0) {
      _aProperty = value;
    }
  }
}

6.可选参数

// Dart有两种形式的可选参数,第一种是可选位置参数,另一种是可选命名参数(用得比较多)
- 位置参数: [String param1, String param2]
- 命名参数: {String param1, String param2}

两者选其一

// 必选参数
int sum(int a, int b) {
  return a + b;
}
print(sum(1, 2));  // 3

// 可选位置参数
int sum(int a, int b, [int c]) {
  if (c != null) { 
    return a + b + c;
  }
  return a + b;
}
print(sum(1, 2));  // 3
print(sum(1, 2, 3));  // 6

// 可选命名参数
int sum(int a, int b, {int c}) {
  if (c != null) { 
    return a + b + c;
  }
  return a + b;
}
print(sum(1, 2));  // 3
print(sum(1, 2, c: 3));  // 6

7.构造器简便写法

class MyColor {
  int red;
  int green;
  int blue;

  MyColor(this.red, this.green, this.blue);
  /* 等价于
  MyColor() {
      this.red = red;
      this.green = green;
      this.blue = blue;
  } */

}

final color = MyColor(80, 80, 128);


8.Initializer lists

不知道怎么翻译, 举了一个序列化和反序列化的例子

class User {
  String user;
  String pwd;

  User();
  // fromJson构造器,用于赋初值(Initializer lists), 并对传入的值进行校验(这部分可省略)
  User.fromJson(Map<String, dynamic> json):
    assert(json['user'] != ""), assert(json['pwd'] != ""),
    user = json['user'], pwd = json['pwd'];
  /*
    等价于
    static User fromJson(Map<String, dynamic> json){
      User u = new User();
      u.user = json['user'];
      u.pwd = json['pwd'];
      return u;
    }
  */

  // 这个例子其实就是Dart中json数据的序列化和反序列化, fromJson是序列化,toJson是反序列化
  Map<String, dynamic> toJson() => {
    'user': user,
    'pwd': pwd,
  };
  /*
    等价于
    Map<String, dynamic> toJson() {
      var map = new Map<String, dynamic>();
      map['user'] = user;
      map['pwd'] = pwd;
      return map;
    }
  };
  
  */


}

void main() {
  Map<String, dynamic> testData = {'user': 'aa', 'pwd': 'bb'};
  User u = User.fromJson(testData); 
  print(u); // Instance of 'User'

  Map testDataR = u.toJson();
  print(testDataR);  // {user: aa, pwd: bb}
}

9.命名构造器(Named constructors)

初看时,其实不明白为什么叫命令构造器,官方文档只解释说“命名构造器的作用是为了让一个类有多个构造器”。不过看久了就发现,
我们可以通过"类名.自定义名" 来创建构造器, 如下面的 Point.origin(), Point.helloWorld(), 你想定义什么名字就什么名字,这才明白命名构造器的含义。

class Point {
  num x, y;

  Point({this.x, this.y});  // 与官方文档不同

  Point.origin() {
    x = 0;
    y = 0;
  }

  Point.helloWorld() {
  x = 1;
  y = 1;
}
}

final myPoint1 = Point();
final myPoint2 = Point.origin();
print(myPoint1.x);  // null
print(myPoint2.y);  // 0

10.工厂构造器(Factory constructors)

// Java的工厂模式
public interface Shape {
   void draw();
}

public class Square implements Shape {
   @Override
   public void draw() {
      System.out.println("Inside Square::draw() method.");
   }
}
public class Circle implements Shape {
   @Override
   public void draw() {
      System.out.println("Inside Circle::draw() method.");
   }
}

public class ShapeFactory {
   //使用 getShape 方法获取形状类型的对象
   public Shape getShape(String shapeType){
      if(shapeType == null){
         return null;
      }        
      if(shapeType.equalsIgnoreCase("circle")){
         return new Circle();
      } else if(shapeType.equalsIgnoreCase("square")){
         return new Square();
      }
      return null;
   }
}

public class FactoryPatternDemo {
   public static void main(String[] args) {
      ShapeFactory shapeFactory = new ShapeFactory();
      //获取 Circle 的对象,并调用它的 draw 方法
      Shape shape1 = shapeFactory.getShape("circle");
      shape1.draw();
      //获取 Square 的对象,并调用它的 draw 方法
      Shape shape3 = shapeFactory.getShape("square");
      shape3.draw();
   }
}

// Dart 的工厂模式
// 比Java的更简洁, 但思想不变,其中Shape.fromTypeName可以自定义为其他名字,比如Shape.fromType
class Square extends Shape {
  @override
  void draw() => print("Inside Square::draw() method.");
}

class Circle extends Shape {
  void draw() => print("Inside Circle::draw() method.");
}

class Shape {
  Shape();

  void draw(){}

  factory Shape.fromTypeName(String typeName) {
    if (typeName == 'square') return Square();
    if (typeName == 'circle') return Circle();

    print('I don\'t recognize $typeName');
    return null;
  }
}

Shape shape = Shape();
shape.draw();

Shape square = Shape.fromTypeName('square');
square.draw();

结尾

Dart的构造器真的是非常多, 其中还有 Redirecting constructors(B构造器重定向到A构造器) 和 Const constructors, 就请读者查看官方文档了,链接在最上面(狗手动头)。