一切皆对象

基本类型

num

  1. 包括 int 和 double两种类型,没有float类型

String

  1. 单引号
  2. 双引号
  3. 三个单引号(多行字符串)
  4. r’string\nstirng’ 去掉转译
  5. str * n,输出多个重复字符串
  6. str[index] 输出单个字符
  7. 字符串表达式 “hello ${value1 * 3}” 如果是单个变量可以省略大括号

常用方法

  1. subString()
  2. toLowerCase(),toUpperCase()
  3. startsWith(),endsWith()
  4. trim(),trimLeft(),trimRight()
  5. indexOf(),lastIndexOf()
  6. split(),replaceXXX()

bool

List

数组/列表

  1. 创建
var list = [1,true,'hello'];
var list = const [1,2,3];
var list = new List();

支持混合多个类型
2. 修改/索引

list[0] = 1;
print(list[0]);

常用方法

  1. [],length
  2. add(),insert()
  3. remove(),clear()
  4. indexOf(),lastIndexOf()
  5. sort(),sublist()
  6. shuffle(),asMap(),forEach()
    forEach参数为一个函数, list.forEach(print);使用print输出每个变量

Map

  1. 创建
var m1 = {'first':'dart','second':'java'};
var m1 = const {'first':'dart','second':'java'};
var m1 = new Map();

常用操作

  1. [],length
  2. isEmpty(),isNotEmpty()
  3. Keys,Values
  4. containsKey(),containsValue()
  5. remove()
  6. forEach()

dynamic

动态类型 var定义的就是动态类型

var list = new List<dynamic>();
list.add(true);
list.add(1);
list.add("hello");
print(list);

可以通过动态类型的范型,定义一个list,这样就可以填充各种类型的对象

运算符

  1. 算数运算符: +,-,*,/,~/,%
    注意: / 是浮点除法, ~/ 是整除

  2. 递增递减 ++var,var++,–var,var–

  3. 关系运算符 ==,!=,>,<,>=,<=

== 判断内容是否相等

  1. 逻辑运算符 !,&&,||
  2. 赋值运算符 =,??=
var b;
b ??= 10;

如果b为空则赋值为10

  1. 复合运算符 +=,-=,*=,/=,%=,~/=

条件表达式

  1. 三目运算符 condition? expr1: expr2
  2. ??运算符 expr1 ?? expr2
    如果expr1为空,值为expr2
var a;
var b = 10;
var c = a ?? b;

c 输出为 10

控制流语句

条件语句

  1. if
  2. if … else if
  3. if … else if … else

循环语句

  1. for
var list = [1,2,3,4];
for(var i=0;i<list.length;i++){
    print(list[i]);
}
  1. for … in
var list = [1,2,3,4];
for(var item in list){
    print(item);
}
  1. while
  2. do … while
  3. break continue 类c语法

switch … case

  1. num,String,编译期常量,对象,枚举
  2. 非空case 必须有一个break
  3. default处理默认情况
  4. continue 跳转标签
var a = 'a';
switch(a){
  TAG1:
  case 'a':
    print('aaa');
  break;
  case 'b':
    print('bbb');
  continue TAG1;
  case 'c':
    print('ccc');
  break;
}

Function

返回类型 方法名称 (参数1,参数2,…){
方法体 …
return 返回值
}

  1. 方法也是对象,类型为 Function
  2. 返回值类型,参数类型都可以省略
  3. 箭头语法 => expr 是 {return expr;}的缩写.只适用于一个表达式
fun1(v) => "value:${v}";
  1. 方法都有返回值,如果没有指定,默认return null在最后执行
    可以在函数定义时,定义为void ,但是函数仍然会返回null,只是在编辑器阶段会有提示(以编辑器决定)

  2. 可选参数

可选命名参数 {param1,param2,…}

fun1(String name,{int age,String gender}){
    print("name=${name},age=${age},gender=${gender}");
}

fun1("张三");
//name=张三,age=null,gender=null

fun1("张三",age=10);
//name=张三,age=10,gender=null

fun1("张三",age=10,gender="男");
//name=张三,age=10,gender=男


fun1("张三",gender="男");
//name=张三,age=null,gender=男

可选位置参数 [param1,param2,…]

fun2(String name,[int age,String gender]){
    print("name=${name},age=${age},gender=${gender}");
}

fun2("张三")
//name=张三,age=null,gender=null

fun2("张三",10);
//name=张三,age=10,gender=null

fun2("张三",10,"男");
//name=张三,age=10,gender=男
  1. 参数默认值

使用 = 在可选参数指定默认值
默认值只能是编译时常量

如果存在具体参数,可选参数声明,必须在参数后面

方法对象

void fun1(){};

var f = fun1;
f();

void fun2(String f(par1)){

}

fun2 请求一个String返回值的方法对象参数

匿名方法

(参数1,参数2,…){
方法体…
return 返回值
}

可以赋值给变量
可以在其他方法中直接调用和传递其他方法

var fun1 = (str){
    print(str);
};

fun1("hello");

// 直接调用
((){print(1);})();

闭包

  1. 闭包也是一个方法(对象)
  2. 闭包定在其他方法内部
  3. 闭包能够访问外部方法内的局部变量,并持有其状态
a(){
    int count = 0;
    return (){
        print(count++);
    };
}

var fun1 = a();
fun1();

a方法返回一个匿名方法,在匿名方法内操作count,而不用担心外部变量污染.

面向对象

创建对象

  1. 使用关键字class 声明类
  2. 使用关键字new创建对象,new可以省略
  3. 所有对象都继承于Object类

属性与方法

  1. 属性默认生成getter和setter方法
  2. 使用final 声明的属性只有getter方法
  3. 属性方法通过 .访问
  4. 方法不能被重载
class Person{
    String name;
    int age;
    final String address; // 只读

    void work(){
        print("Name is $name,Age is $age, hi is working...");
    }
}

var p = new Person();
p.name = "张三";
p.age = 10;
p.work();
//var p = Person();    // new 可以省略

类和成员可见性

  1. Dart中可见星以library(库)为单位
  2. 默认情况下,每一个Dart文件就是一个库
  3. 使用_表示库的私有性
  4. 使用 import导入库

计算属性

  1. 计算属性的值是通过计算而来,本身不存储值
  2. 计算属性赋值,其实是通过计算转换到其他实例变量
class Rectangle{
    num width,height;
    
    num get area => width * height;
    set area(value) {
        width = value / 20;
    }
}

构造方法

  1. 如果没有自定义构造方法,则会有一个默认的构造方法
  2. 如果存在自定义的构造方法,默认的自定义构造方法是无效的
  3. 构造方法不能重载
  4. 构造方法里不能对final属性进行赋值
  5. 构造方法不能有返回值
class Person{

    String name;
    int age;
    
    // 语法糖
    Person(this.name,this.age) ;
    
    // 等效于下面
    //Person(String name,int age){
    //    this.name = name;
    //    this.age = age;
    //}
}

命名构造方法

  1. 使用命名构造方法,可以实现多个构造方法
  2. 使用 类名.方法 的形式实现
class Person{
    String name;
    int age;

    Person(this.name,this.age);
    Person.withName(this.name);
}

常量构造方法

  1. 如果类是不可变状态,额可以把对象定义为编译时常量
  2. 使用const 声明构造方法,并且所有变量都为final
  3. 使用const 声明对象,额可以省略
class Person{

    final String name;
    final int age;

    const Person(this.name,this.age);
}

const p = const Person("张三",12);

工厂构造方法

  1. 工厂构造方法类似于设计模式中的工厂模式
  2. 在构造方法钱添加关键字 facotry 实现一个工厂构造方法
  3. 在工厂构造方法中可返回对象
class Logger {
    final String name;

    factory Logger(String name){
        // 省略很多代码,这里只是举例
        return Logger._internal(name);
    }

    // 私有 命名构造方法
    Logger._internal(this.name);
}

初始化列表

  1. 初始化列表会在构造方法执行之前执行
  2. 使用逗号分割初始化列表
  3. 初始化列表常用于设置final变量的值
class Person{
    final String name;

    Person(String n) : name = n;
}

静态成员

  1. 静态成员既可以是方也可以是属性
  2. 使用static关键字来实现类级别的变量和函数
  3. 静态成员不能访问非静态成员,非静态成员可以访问静态成员
  4. 类中的常量需要使用static const 声明
class Person{
    // 常量必须是静态的
    static const int age = 10;
}

对象操作符

  1. 条件成员的访问 ?. 对象不为空才会继续执行
Person p;
p?.fun1();
  1. 类型转换 as
var p;
p = "hello";
p = new Person();
(p as Person).fun1();
  1. 是否指定类型 is, is!
if(p is Person){
    print('ok');
}

// 不是person类型
if(p is! Person){
    print('error')
}
  1. 级联操作
var p = new Person();
p..name = "张三"
 ..age = 12
 ..fun1();

// 精简写法
var p = new Person()..name = "张三" ..age = 12 ..fun1();

对象中的call方法

  1. 如果类实现了call()方法,则改类对象可以作为方法使用
class Person{
    String call(){
        return "hello";
    }
}

var p = new Person();
print(p());

继承

  1. 使用extends 继承一个类
  2. 子类会继承弗雷的可见属性和方法,不会集成构造方法
  3. 子类能够复写父类的方法.getter和setter
  4. 单继承,多态性
class Person{
    String name;
    int age;
    String _birthday;

    bool get isAdult => age > 18;

    void run(){
        print('Person run');

    }
}


class Student extends Person{
  
    @override
    bool get isAdult => age > 15;
    @override
    void run(){
        print('student run');
        // super.run();
    }
}

@override 标记 可以省略

集成中的构造方法

  1. 子类的构造方法默认会调用弗雷的无名无参构造方法
  2. 如果父类没有无名无参构造方法,则必须显示调用父类构造方法
  3. 在构造方法参数后使用 : 显示调用父类构造方法
class Person{
    String name;

    Person(this.name);
    Person.withName(this.name);
}

class Student extends Person{
    int age;

    Student(String name) : super(name);
    //Student(String name) : super.withName(name); //调用父类命名构造方法
    //Student.withName(String name) : super.withName(name); //新命名构造方法调用父类命名构造方法
}

构造方法执行顺序

  1. 父类的构造方法在子类构造方法体开始执行前的位置调用
  2. 如果有初始化列表,初始化列表会在父类构造方法之前执行
class Student extends Person{
    final String gender;

    Student(String name,String g) : gender = g, super(name);
}

注: 初始化列表必须在父类构造方法之前,两者之间用逗号分隔

抽象类

  1. 抽象类使用abstract 表示,不能直接被实例化
  2. 抽象方法不用abstract 修饰,无实现 (区别于java,不需要关键字)
  3. 抽象类可以没有抽象方法
  4. 有抽象方法的类,必须声明为抽象类
abstract class Person{
   void run();
}

接口

  1. 类和接口是统一的,类就是接口
  2. 每个类都kinship的定义了一个包含所有实例成员的接口
  3. 实现接口,需要重写每个属性和方法
  4. 如果是复用已有类的实现,使用继承(extends)
  5. 如果只是使用已有类的外在行为,使用接口(implements)
class Person{
    String name;
    void run(){
        print('run');
    }
}

class Student implements Person{
    @override 
    String name;

    @override
    void run(){
        print('student run');
    }
}

感觉有些怪异,所以使用抽象类作为接口,更符合以往其他语言的使用习惯

abstract class Person{
    void run();
}

class Student implements Person{
    @override
    void run(){
        print('run');
    }
}

Mixins

  1. Mixins 类似于多继承,是在多类继承中重用一个类代码的方式
  2. 作为Mixin的类不能有显示声明构造方法(命名构造方法也不可以)
  3. 作为Mixin的类只能继承自Object
  4. 使用关键字with链接一个或多个mixin
  5. 多个Mixin中的重名方法,使用最后一个类的方法
  6. 必须先有继承才能使用Mixin
abstract class Engine{
    void work();
}

//汽油引擎
class OilEngine implements Engine{
    @override
    void work(){
        print('work with oil ...');
    }
}

// 电动引擎
class ElectricEngine implements Engine{
    @override
    void work(){
        print('work with electric ...');
    }
}

// 轮胎
class Tyre{
    String name;

}

// 语法糖
class Car = Tyre with ElectricEngine; //电动汽车
class Bus = Tyre with OilEngine;        //烧油汽车

class Car extends Tyre with ElectricEngine{
    @override
    String name;
}

操作符重载

  1. 重载操作服需要在类中定义

返回类型 operator操作符 (参数1,参数2,…){
实现体 …
return 返回值
}

  1. 如果重载==,还需要宠爱对象的hashCode getter方法

  2. 可以重载的操作符
    < + | []

/ ^ []=
<= ~/ & ~
= * << ==

  • % >>
class Person{
    int age;
    Person(this.age);

    bool operator >(Person p){
        return this.age > p.age;
    }

    int operator [](String str){
        if(str == "age"){
            return this.age;        
        }
    }
}

var p1 = Person(12);
var p2 = Person(8);

print(p1 > p2);
print(p1["age"]);

https://www.imooc.com/video/19042