语法基础——Dart语法基础

主函数

void main(){
    print('Hello Word');
}

常量和变量

如果未初始化的变量,其默认值为null

//常量
const a = 10;
//变量
var b = 10;

Dart没有public、protected、和private关键字,标识符(_)表示私有的意思

//默认为public
int a = 10; 
//下划线开头为private
int _a = 10;

final和const都表示常量的意思,其值都不可修改,两者最大的区别

  • final属于运行时变量,在初始化的时候去创建的变量
  • const属于编译时变量,在编译期间就被创建的变量
final a = 10;
const b = 10;

class Main(){
    final a = 10;
    //如果const变量在类中,需要加上static
    //因为类未初始化,该值无法被视为编译时变量,否则会报错
    static const b = 10;
}

dart语法的const相当于java这种写法

private static final int a = 10;

若干个表达式引用为编译时常量,其结果也是编译时常量

const a = "Hello";
const b = "Word";

const c = "$a $b";

类型

1、基本类型

Dart内置的可用类型

  • numbers:只支持int、double
  • strings
  • booleans
  • lists
  • maps
  • runes
  • symbols

2、number

  • 运算符:+、-、*、/、~/、%
  • 常用属性:isNaN、isEven、isOdd
  • 常用方法:abs()、round()、floor()、ceil()、toInt()
  • 特殊运算符: ?.、??、??=

/~/的区别

int a = 10;
int b = 2;
print(a/b);  //5.0
print(a~/b); //5

????=的区别

//??属于条件表达式,如果b是null,则执行toString()并返回其结果,如果不是null,则返回其值
b ?? b.toString();

//??=属于赋值表达式,如果b是null,则赋值给b,如果不是null,则b的值保持不变
b ??= value;

?.??的配合使用

//padding为空,则返回1,padding不为空,则返回padding.value
int a = padding?.value ?? 1

3、boolean

true和false所创建的对象都是编译时常量。当Dart需要一个布尔值的时候,只有true对象才被认为是true,所有其他的值都是flase

4、string

String str1 = 'HelloWord';          //普通字符串
String str2 = """;                  //段落
    
        go
    
""";
String str3 = r'Hello /n Word';     //不转义
print(str3 * 5);                    //重复5次
print(str3 == str4);                //相等
print(str3[0]);                     //获取字符
print('a + b = ${a + b}')           //插值表达式

5、list

var list = [1,2,3];
var list = const [1,2,3];           //定义不可变列表
var list = new List();
var list = new List.generate(1000, (i)=>"Item $i");

6、map

var map = {'1':'c','2':'java'};
var map = const{'1':'c','2':'java'}; //定义不可变映射
var map = new Map();

7、dynamic

dynamic a = 10;                      //任意类型变量
var list = new List();      //任意类型列表

8、runes

runes代表字符串的Unicode编码

Runes input = new Runes('\u2665  \u{1f605}  \u{1f60e}  \u{1f47b}  \u{1f596}  \u{1f44d}');
print(new String.fromCharCodes(input));  //输出一排表情

9、enum

enum Color {red,green,blue}          //枚举的定义
assert(Color.red.index == 0);        //枚举索引获取
List colors = Color.values;   //枚举列表获取

操作符

operator关键字可以复写操作符

class Vector {
    final int x;
    final int y;
    const Vector(this.x, this.y);
    
    /// Overrides + (a + b).
    Vector operator +(Vector v) {
        return new Vector(x + v.x, y + v.y);
    }
    
    /// Overrides - (a - b).
    Vector operator -(Vector v) {
        return new Vector(x - v.x, y - v.y);
    }
}

函数

1、函数的返回类型和参数类型都是可以省略的

getPerson(name,age){
    return new Person(name,age);
}

2、函数的实现体可以通过符号进行表示

getPerson(name,age) => new Person(name,age);

3、可选参数(重载函数)

花括号参数表示可选命名参数

getPerson(name,{age,weight}) => new Person(name,age,weight);
getPerson("张三",weight:55);

方括号参数表示可选位置参数,不需要别名,但是位置必须是固定的参数

getPerson(name,[age,weight]) => new Person(name,age,weight);
getPerson("张三",18,55);

4、默认参数

getPerson(name,age=18) => new Person(name,age);

5、构造函数

@required表示必须传参

class Person{
    var name;
    var age;
    //这里默认等同于this.name=name,this.age=age
    Person({@required this.name,this.age}); 
}

当前为StatelessWidget组件中的构造方法

class MyApp extends StatelessWidget{
    final List items;
    MyApp({Key key,@required this.items}):super(Key:key);
}

常量构造函数

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

命名构造函数

class Point {
    num x;
    num y;
    
    Point(this.x, this.y);
    
    //可以直接命名的构造函数,命名构造函数也是可以直接实例化的
    Point.fromJson(Map json) {
        x = json['x'];
        y = json['y'];
    }
}

默认情况下,子类的构造函数会自动调用超类的无名无参数的默认构造函数,如果超类没有无名无参数构造函数,则你需要手工的调用超类的其他构造函数,在构造函数参数后使用冒号可以调用超类构造函数。如果提供了一个initializer list(初始化参数列表),则初始化参数列表在超类构造函数执行之前执行。下面是构造函数执行顺序:

  1. initializer list(初始化参数列表)
  2. superclass’s no-arg constructor(超类的无名构造函数)
  3. main class’s no-arg constructor(主类的无名构造函数)
class Point {
    num x;
    num y;
    
    Point(this.x, this.y);
    
    //初始化参数列表用冒号展开
    //初始化表达式等号右边的部分不能访问this
    Point.fromJson(Map jsonMap)
      : x = jsonMap['x'],
        y = jsonMap['y'] {
        print('In Point.fromJson(): ($x, $y)');
    }
}

重定向构造函数

class Point {
    num x;
    num y;
    
    Point(this.x, this.y);
    //类似于重载
    Point.alongXAxis(num x) : this(x, 0);
}

工厂方法构造函数

class Logger {

    static final Map _cache = {};
    //使用factory关键字表示工厂方法,其实现类似于单例模式的实现
    factory Logger(String name) {
        if (_cache.containsKey(name)) {
            return _cache[name];
        } else {
            final logger = new Logger._internal(name);
            _cache[name] = logger;
            return logger;
        }
    }
}

6、get和set

num get right             => left + width;
    set right(num value)  => left = value - width;
num get bottom            => top + height;
    set bottom(num value) => top = value - height;

7、函数参数

函数可以作为参数

final values = [1, 2, 3, 5, 10, 50];
//map和forEach参数里面可以传递函数
values.skip(1).take(3).map(func).forEach(print);

例如:forEach的源码实现

void forEach(void f(E element)) {
    for (E element in this) f(element);
}

8、匿名方法

var fun = (){
    print("Hello Word");
}

9、闭包

闭包最大的作用是可以访问方法体中的成员变量

count(){
    int count = 0;
    return (){
        print(count++);  
    };
}

void main(){
    var fun = count();
    fun(); //1
    fun(); //2
    fun(); //3
}

10、返回值

所有的函数都返回一个值,如果没有指定返回值,则默认把语句return null;作为函数的最后一个语句执行

11、静态函数

静态函数不再类实例上执行,所以无法访问this

异常

异常的捕获可以用on关键字进行捕获对应的异常,或者用rethrow关键字进行重新抛出异常

try {
  breedMoreLlamas();
} on OutOfLlamasException {
  // 指定捕获OutOfLlamasException
  buyMoreLlamas();
} on Exception catch (e) {
  // 指定捕获Exception类型的异常
  print('Unknown exception: $e');
} catch (e) {
  // 任意异常
  print('Something really unknown: $e');
  rethrow; // 重新抛出该异常
}

导包

1、指定别名

当有类名冲突的时候,可以用不同的别名进行区分

import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;

Element element1 = new Element();           //使用lib1的Element类
lib2.Element element2 = new lib2.Element(); //使用lib2的Element类

2、导入指定功能

如果你只使用库的一部分功能,则可以选择需要导入的内容

import 'package:lib1/lib1.dart' show foo;  //只导入foo库
import 'package:lib2/lib2.dart' hide foo;  //导入除foo库的所有其他库

3、延迟导入

下面是一些使用延迟加载库的场景

  • 减少APP的启动时间
  • 执行A/B测试,例如尝试各种算法的不同实现
  • 加载很少使用的功能,例如可选的屏幕和对话框
import 'package:deferred/hello.dart' deferred as hello;

当需要使用的时候,使用库标识符调用 loadLibrary()函数来加载库,使用 await 关键字暂停代码执行一直到库加载完成

greet() async {
    await hello.loadLibrary();
    hello.printGreeting();
}

级联调用

对象的方法和成员变量都可以进行级联调用,类似于Java的链式调用

//案例一
void main(){
 num x = 10;
 num y = 42; // not used
 var p = new Point();
 p..log('start')
  ..x = x
  ..scale(10)
  ..log('scaled')
  ..x = x + 1
  ..y = x + p.x + p.y;
 print('p.x = ${p.x}, p.y = ${p.y}. x = $x');
}

//案例二
front
..beginPath()
..fillStyle = penColor
..arc(tx, ty, penWidth/2+2, 0, PI2, true)
..fill()
..moveTo(wx, wy)
..strokeStyle = "black"
..lineTo(tx, ty)
..closePath()
..stroke();

//案例三
querySelector('#button') // Get an object.
  ..text = 'Confirm'   // Use its members.
  ..classes.add('important')
  ..onClick.listen((e) => window.alert('Confirmed!'));

//案例四
//级联调用也可以嵌套
final addressBook = (new AddressBookBuilder()
      ..name = 'jenny'
      ..email = '[email protected]'
      ..phone = (new PhoneNumberBuilder()
            ..number = '415-555-0100'
            ..label = 'home')
          .build())
    .build();

异步支持

1、声明异步方法

一个异步方法是函数体被标记为async的方法

checkVersion() async {
    // ...
}

使用asyncawait的代码是异步的,要使用await,其方法必须带有async关键字

checkVersion() async {
    var version = await lookUpVersion();
}

可以使用try-catch,和finally来处理使用await的异常

try {
    server = await HttpServer.bind(InternetAddress.LOOPBACK_IP_V4, 4044);
} catch (e) {

}

异步方法返回值为Future类型

String lookUpVersionSync() => '1.0.0';
Future lookUpVersion() async => '1.0.0';

在循环中使用异步

await for (var request in requestServer) {
    handleRequest(request);
}

可调用类

//可以把类当做方法使用
class WannabeFunction {
  call(String a, String b, String c) => '$a $b $c!';
}

main() {
  var wf = new WannabeFunction();
  var out = wf("Hi","there,","gang");
  print('$out'); //Hi there, gang!
}

别名

typedef能对方法进行重命名,且只能使用在function类型,在构造函数中也可以传递方法

typedef int Compare(Object a, Object b);

class SortedCollection {
    Compare compare;
    SortedCollection(this.compare);
}

int sort(Object a, Object b) => 0;

main() {
    SortedCollection coll = new SortedCollection(sort);
    assert(coll.compare is Function);
    assert(coll.compare is Compare);
}

注解

1、系统自带注解

@deprecated、 @override、@proxy

2、自定义注解

library todo;

class todo {
    final String who;
    final String what;
    
    const todo(this.who, this.what);
}

import 'todo.dart';

@todo('xuyingjun', 'make this do something')
void doSomething() {
    print('do something');
}

你可能感兴趣的:(语法基础——Dart语法基础)