Dart 基本语法

2019-04-18  本文已影响0人  风之化身呀

Dart 语言集合了 Java、JavaScript、C、TypeScript 等语言的优势,可以说是集百家之长的一门编程语言,可以用与 web 编程服务端编程以及 app 编程(Flutter),目前主要用于 Flutter 开发。以下是几点重要的概念:

1、基本语法

1.1、变量

var str = 'abc';
str = 'def';  // ok
str = 123; // error
String str = 'abc' // 与 var str='abc' 等价
dynamic t;
 Object x;
 t = "hi world";
 x = 'Hello Object';
 //下面代码没有问题
 t = 1000;
 x = 1000;

dynamic与Object不同的是,dynamic声明的对象编译器会提供所有可能的组合, 而Object声明的对象只能使用Object的属性与方法, 否则编译器会报错.

 var foo = const [1];  // 表示这个数组的值不能变化,而不是数组的地址
 foo[0]=1;  // error
// String -> int
var one = int.parse('1');
assert(one == 1);

// String -> double
var onePointOne = double.parse('1.1');
assert(onePointOne == 1.1);

// int -> String
String oneAsString = 1.toString();
assert(oneAsString == '1');

// double -> String
String piAsString = 3.14159.toStringAsFixed(2);
assert(piAsString == '3.14');
String a='123';
var b='123'; // 等价于 var b='$a';
var name = 'Bob';
if (name) {
  // Prints in JavaScript, not in Dart.
  print('You have a name!');
}
var list = [1, 2, 3];
assert(list.length == 3);

var constantList = const [1, 2, 3];
constantList[1] = 1; // causes an error.
var gifts = {
// Keys      Values
  'first' : 'partridge',
  'second': 'turtledoves',
  'fifth' : 'golden rings'
};

var gifts = new Map();
gifts['first'] = 'partridge';
gifts['second'] = 'turtledoves';
gifts['fifth'] = 'golden rings';
enum Color {
  red,
  green,
  blue
}

枚举类型中的每个值都有一个 index getter 函数, 该函数返回该值在枚举类型定义中的位置(从 0 开始)。 例如,第一个枚举值的位置为 0, 第二个为 1.

1.2、函数 Function

bool isNoble(int atomicNumber) {
  ...
}
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
[1,2,3].forEach(a=>print(a)); // err
[1,2,3].forEach((a)=>print(a)); // ok
enableFlags({bool bold, bool hidden}) {
  // ...
}

调用方法的时候,你可以使用这种形式 paramName: value 来指定命名参数

enableFlags(bold: true, hidden: false);

2、可选位置参数
把一些方法的参数放到 [] 中就变成可选 位置参数了:

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

// 不使用可选参数调用
assert(say('Bob', 'Howdy') == 'Bob says Howdy');
// 使用可选参数
assert(say('Bob', 'Howdy', 'smoke signal') ==
    'Bob says Howdy with a smoke signal');
void enableFlags({bool bold = false, bool hidden = false}) {
  // ...
}
String say(String from, String msg,
    [String device = 'carrier pigeon', String mood]) {
  var result = '$from says $msg';
  if (device != null) {
    result = '$result with a $device';
  }
  if (mood != null) {
    result = '$result (in a $mood mood)';
  }
  return result;
}

assert(say('Bob', 'Howdy') ==
    'Bob says Howdy with a carrier pigeon');
void main(List<String> arguments) {
  print(arguments);

  assert(arguments.length == 2);
  assert(int.parse(arguments[0]) == 1);
  assert(arguments[1] == 'test');
}
var list = ['apples', 'oranges', 'grapes', 'bananas', 'plums'];
list.forEach((i) {
  print(list.indexOf(i).toString() + ': ' + i);
});

1.3、操作符

只记录与JS语言不一致的操作符

assert(5 / 2 == 2.5);   // Result is a double
assert(5 ~/ 2 == 2); 
void main() {
  const c = [1,2];
  var a = c;
  var b = c;
  print(a == b);
  print(identical(a,b));
}
if (emp is Person) { // Type check
  emp.firstName = 'Bob';
}
(emp as Person).firstName = 'Bob';
a = value;   // 给 a 变量赋值
b ??= value; // 如果 b 是 null,则赋值给 b;
             // 如果不是 null,则 b 的值保持不变
expr1 ?? expr2 // expr1 为 null 时执行 expr2
querySelector('#button') // Get an object.
  ..text = 'Confirm'   // Use its members.
  ..classes.add('important')
  ..onClick.listen((e) => window.alert('Confirmed!'));

1.4、类

class Point {
  num x;
  num y;
  Point(this.x, this.y);
}
class Point {
  num x;
  num y;

  Point(this.x, this.y);

  // Named constructor 只有当名字冲突的时候才使用 this。否则的话, Dart 代码风格样式推荐忽略 this。
  Point.fromJson(Map json) {
    x = json['x'];
    y = json['y'];
  }
}

注意:构造函数不能继承,所以超类的命名构造函数 也不会被继承。如果你希望 子类也有超类一样的命名构造函数, 你必须在子类中自己实现该构造函数。

import 'dart:math';

class Point {
  final num x;
  final num y;
  final num distanceFromOrigin;

  Point(x, y)
      : x = x,
        y = y,
        distanceFromOrigin = sqrt(x * x + y * y);
}

main() {
  var p = new Point(2, 3);
  print(p.distanceFromOrigin);
}
class Point {
  num x;
  num y;

  // The main constructor for this class.
  Point(this.x, this.y);

  // Delegates to the main constructor.
  Point.alongXAxis(num x) : this(x, 0);
}
class Television {
  void turnOn() {
    _illuminateDisplay();
    _activateIrSensor();
  }
  // ...
}

class SmartTelevision extends Television {
  void turnOn() {
    super.turnOn();
    _bootNetworkInterface();
    _initializeMemory();
    _upgradeApps();
  }
  // ...
}

可以使用 @override 注解来 表明你的函数是想覆写超类的一个函数:

class A {
  @override
  void noSuchMethod(Invocation mirror) {
    // ...
  }
}
class Musician extends Performer with Musical {
  // ...
}
class Musical {
  bool canPlayPiano = false;
  bool canCompose = false;
  bool canConduct = false;

  void entertainMe() {
    if (canPlayPiano) {
      print('Playing piano');
    } else if (canConduct) {
      print('Waving hands');
    } else {
      print('Humming to self');
    }
  }
}

1.5、泛型

1、使用泛型的原因是减少重复的代码。 泛型可以在多种类型之间定义同一个实现, 同时还可以继续使用检查模式和静态分析工具提供的代码分析功能。

var names = <String>['Seth', 'Kathy', 'Lars'];
var pages = <String, String>{
  'index.html': 'Homepage',
  'robots.txt': 'Hints for web robots',
  'humans.txt': 'We are people, not machines'
};

2、当使用泛型类型的时候,你 可能想限制泛型的具体类型。 使用 extends 可以实现这个功能:

// T must be SomeBaseClass or one of its descendants.
class Foo<T extends SomeBaseClass> {...}

3、泛型函数

T first<T>(List<T> ts) {
  // ...Do some initial work or error checking, then...
  T tmp ?= ts[0];
  // ...Do some additional checking or processing...
  return tmp;
}

1.6、其他

import 'dart:io';
import 'package:mylib/mylib.dart';
import 'package:utils/utils.dart';

2、如果你导入的两个库具有冲突的标识符, 则你可以使用库的前缀来区分。 例如,如果 library1 和 library2 都有一个名字为 Element 的类, 你可以这样使用:

import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;
// ...
Element element1 = new Element();           // Uses Element from lib1.
lib2.Element element2 = new lib2.Element(); // Uses Element from lib

3、导入库的一部分

// Import only foo.
import 'package:lib1/lib1.dart' show foo;

// Import all names EXCEPT foo.
import 'package:lib2/lib2.dart' hide foo;

4、库的延迟加载,使用 deferred as 来 导入,使用库标识符调用 loadLibrary() 函数来调用

import 'package:deferred/hello.dart' deferred as hello;
greet() async {
  await hello.loadLibrary();
  hello.printGreeting();
}
Future.delayed(new Duration(seconds: 2),(){
   //return "hi world!";
   throw AssertionError("Error");
}).then((data){
   //执行成功会走到这里 
   print(data);
}).catchError((e){
   //执行失败会走到这里   
   print(e);
}).whenComplete((){
   //无论成功或失败都会走到这里
});

有些时候,我们需要等待多个异步任务都执行结束后才进行一些操作

Future.wait([
  // 2秒后返回结果  
  Future.delayed(new Duration(seconds: 2), () {
    return "hello";
  }),
  // 4秒后返回结果  
  Future.delayed(new Duration(seconds: 4), () {
    return " world";
  })
]).then((results){
  print(results[0]+results[1]);
}).catchError((e){
  print(e);
});

2、Stream
Stream 也是用于接收异步事件数据,和Future 不同的是,它可以接收多个异步操作的结果

Stream.fromFutures([
  // 1秒后返回结果
  Future.delayed(new Duration(seconds: 1), () {
    return "hello 1";
  }),
  // 抛出一个异常
  Future.delayed(new Duration(seconds: 2),(){
    throw AssertionError("Error");
  }),
  // 3秒后返回结果
  Future.delayed(new Duration(seconds: 3), () {
    return "hello 3";
  })
]).listen((data){
   print(data);
}, onError: (e){
   print(e.message);
},onDone: (){

});
// 依次输出
hello 1
Error
hello 3

2、最佳实践

2.1、字符串

raiseAlarm(
    'ERROR: Parts of the spaceship are on fire. Other '
    'parts are overrun by martians. Unclear which are which.');
'Hello, $name! You are ${year - birth} years old.';

2.2、集合

var points = [];
var addresses = {};
// bad
var points = new List();
var addresses = new Map();
if (lunchBox.isEmpty) return 'so hungry...';
if (words.isNotEmpty) return words.join(' ');
// bad
if (lunchBox.length == 0) return 'so hungry...';
if (!words.isEmpty) return words.join(' ');
var aquaticNames = animals
    .where((animal) => animal.isAquatic)
    .map((animal) => animal.name);

2.3、变量

class Circle {
  num radius;

  num get area => math.PI * radius * radius;
  num get circumference => math.PI * 2.0 * radius;

  Circle(this.radius);
}
Map<int, List<Person>> groupByZip(Iterable<Person> people) {
  var peopleByZip = <int, List<Person>>{};
  for (var person in people) {
    peopleByZip.putIfAbsent(person.zip, () => <Person>[]);
    peopleByZip[person.zip].add(person);
  }
  return peopleByZip;
}
// bad
Map<int, List<Person>> groupByZip(Iterable<Person> people) {
  Map<int, List<Person>> peopleByZip = <int, List<Person>>{};
  for (Person person in people) {
    peopleByZip.putIfAbsent(person.zip, () => <Person>[]);
    peopleByZip[person.zip].add(person);
  }
  return peopleByZip;
}

2.4、成员

class Box {
  final contents = [];
}
bool ready(num time) => minTime == null || minTime <= time;
class Box {
  var value;

  void clear() {
    update(null);
  }

  void update(value) {
    this.value = value;
  }
}
// bad
class Box {
  var value;

  void clear() {
    this.update(null);
  }

  void update(value) {
    this.value = value;
  }
}

2.5、构造函数

class Point {
  num x, y;
  Point(this.x, this.y);
}
// bad
class Point {
  num x, y;
  Point(num x, num y) {
    this.x = x;
    this.y = y;
  }
}
// bad
class Point {
  int x, y;
  Point(int this.x, int this.y);
}
class Point {
  int x, y;
  Point(this.x, this.y);
}
// bad
class Point {
  int x, y;
  Point(this.x, this.y) {}
}
View(Style style, List children)
    : _children = children,
      super(style) {
// bad
View(Style style, List children)
    : super(style),
      _children = children {
上一篇 下一篇

猜你喜欢

热点阅读