Dart学习笔记-基础篇

声明

本笔记是我自己在学习Dart语言基础的时候做的笔记。有些代码只是为了演示用法,不要纠结逻辑。

本笔记是站在一个Android开发者的角度上记录的,Dart中与Java相同的地方没有做记录,请谅解。阅读本笔记将默认你是一个Android或Java开发者。

一、声明变量与常量

Dart中声明变量有以下几种方式:

//第一种方式
var str = '这是字符串';
var str2 = "这是字符串2";
var str3 = '''
    这是字符串3
    这是字符串3的第二行
    ''';
var str4 = """
    这是字符串4
    这是字符串4的第二行
    """;
var age = 24;

//第二种方式
String str = '这是字符串';
int age = 25;

Dart中的常量使用finalconst关键字修饰,const定义时就要赋值,final可以使用时在赋值,final也是运行时常量,在运行时也不能被修改。

//使用final定义。
final String name = '李四';
final int age = 24;
//使用const定义。
const String gender = '男';
const int height = 165;

二、自定义函数

1. 可选参数

可选参数的作用就类似Java语言中的方法重载。

/**
 * 定义可选参数的自定义函数。
 * @userName 为必传参数。
 * @age 可选参数
 */
String printUserInfo(String userName, [int age]){
  return "姓名:$userName-年龄:${age==null??"未知"}";
}

//调用演示
print(printUserInfo("张三"));

print(printUserInfo("李四", 24));

//输出结果
姓名:张三-年龄:未知
姓名:李四-年龄:24

2. 可选参数-带默认值

可选参数也支持赋值默认值,也就是说,如果调用方法的时候没有传该参数,那么就就会使用默认值赋值。

/**
 * 定义可选参数的自定义函数。
 * @userName 为必传参数。
 * @gander 可选参数
 * @age 可选参数
 */
String printUserInfo(String userName, [String gender='男', int age]){
  return "姓名:$userName-性别:$gender-年龄:${age==null??"未知"}";
}

//调用演示
print(printUserInfo("张三"));

print(printUserInfo("小微", '女'));

//输出结果
姓名:张三-性别:男-年龄:未知
姓名:小微-性别:女-年龄:未知

3. 命名参数

命名参数几乎和可选参数一样,只是有以下两点不同:

1).写法不同,要将[]中括号换成{}花括号。

2).用法不同,可选参数在调用时必须按照方法中声明的顺序传参,而命名参数则不需要按照顺序。这是因为命名参数在传参时必须制定参数名。

/**
 * 定义命名参数的自定义函数。
 * @userName 为必传参数。
 * @gander 可选参数
 * @age 可选参数
 */
String printUserInfo(String userName, {String gender='男', int age=23}){
  return "姓名:$userName-性别:$gender-年龄:$age";
}

//调用演示
print(printUserInfo("张三", age:20));

print(printUserInfo("小微", age:18, gender:'女'));

//输出结果
姓名:张三-性别:男-年龄:20
姓名:小微-性别:女-年龄:18

4. 把方法做为参数

其实就是参数类型为一个Function。

//第一种方式
void fn1(fn){
  fn();
}

void fn2(){
  print('这里是方法2');
}

//调用演示
fn1(fn2);


//第二种方式
var fn3 = (){
    print('这里是方法3');
};

//调用演示
fn1(fn3);

//输出结果
这里是方法2
这里是方法3

5. 匿名函数

//无参匿名方法
var fun1 = (){
  print('无参匿名方法');
};
//有参匿名方法
var fun2 = (String arg){
    print(arg);
};

三、类

1. 权限修饰符

Dart语言中并没有像Java一样有publicprivateprotected这些权限修饰符。Dart中只有一个权限修饰符_(下划线)。下划线修饰符类似于Java中的默认修饰符,在同一个.dart文件中是公开的,不同的.dart文件中是私有的。

class Persion{
  //私有成员变量姓名。
  String _name;
  //私有成员变量年龄
  int _age;

  //构造方法
  Persion(String name, int age){
    _init(name, age);
  }

  //私有init方法。
  void _init(String name, int age){
    this._name = name;
    this._age = age;
  }

  //公共方法获取姓名。
  String getName(){
    return this._name;
  }

  //公共方法获取年龄。
  int getAge(){
    return this._age;
  }
}

2. 构造方法

​ 1). 默认的构造方法与Java一样,但Dart支持可选参数

​ 2).命名构造

​ 命名构造顾名思义就是给构造方法定义一个名字,在使用的时候直接使用这个名字即可,其实在使用时的代码看起来更像是Java中的静态方法,只是在静态方法中返回了这个对象而已。

class Persion{

  String name;
  int age;

  /**
   * 定义命名构造
   */
  Persion.create(String name, int age){
    this.name = name;
    this.age = age;
  }
}

//使用
var persion = Persion.create("张三", 23);

print("${persion.name}-${persion.age}")

//输出
张三-23

3. getter 和 setter 方法

Dart中的方法与Java中的方法一样,在调用时后面必须要跟上(),比如persion.getName(),但是使用get或set定义方法后就可以像成员变量一样使用。

class Persion{

  String _name;
  int _age;

  /**
   * 定义命名构造
   */
  Persion(String name, int age){
    this._name = name;
    this._age = age;
  }

  get isBaby{
    return this._age <= 2;
  }

  set age(int age){
    this._age = age;
  }
}

//使用
var persion = new Persion('张三', 23);
persion.age = 1;

print(persion.isBaby);

//输出
true

4. 初始化列表

在Dart中我们可以在构造方法执行之前初始化对象的变量。

class Persion{

  String name;
  int age;

  /**
   * 定义命名构造
   */
  Persion(): this.name = '李四', this.age = 24{
  }
}

//使用
var persion = new Persion();
print("${persion.name}-${persion.age}");

//输出
李四-24

5. 静态属性和静态方法

Dart中的静态属性和静态方法与Java中一致,静态方法中不能访问非静态成员,非静态方法中可以访问静态成员。

class Persion{
  static String name = '王五';
  static int age = 25;

  static isBaby(){
    return age <= 2;
  }
}

//使用
print("${Persion.name}-${Persion.age}-${Persion.isBaby()}");

//输出
王五-25-false

6. 对象操作符

  1. ? 条件运算符

    var persion
    persion?.getName() //加上 ? 表示如果persion为null则不会getName方法,相当于非null判断。
    
  2. as 类型转换符(强转)

  3. is 类型判断(相当于Java中的instanceOf)

  4. .. 级联操作(连缀)

    class Persion{
      String name;
      int age;
    
      void printInfo(){
        print("$name-$age");
      }
    }
    
    //使用
    Persion persion = new Persion();
    
    persion..name = '赵六'
           ..age = 36
           ..printInfo();
    
    //输出
    赵六-26
    

7. 继承

Dart中关于继承的规则基本和Java一致。

class Persion{
  String name;
  int age;

  Persion(String name, int age){
      this.name = name;
      this.age = age;
  }

  void printInfo(){
    print("$name-$age");
  }
}

class Man extends Persion{
  Man(String name, int age) : super(name, age);//如果父类没有空参构造子类就必须要调用父类的构造。
}

//使用
var man = new Man('如花', 28)
man.printInfo()
  
//输出
如花-28

上面的代码是正常的继承关系,下面是被继承的类有命名构造。

class Persion{
  String name;
  int age;

  Persion.create(String name, int age){
      this.name = name;
      this.age = age;
  }

  void printInfo(){
    print("$name-$age");
  }
}

class Man extends Persion{
  Man(String name, int age) : super.create(name, age);//调用super的命名构造。
}

复写父类方法。

class Man extends Persion{
  Man(String name, int age) : super.create(name, age);

  //覆盖父类的方法
  @override
  void printInfo() {
    print('我是一个男人');
  }
}

其他的基本与Java一致,这里就不再详细记录了。

四、抽象类&接口

Dart中的抽象类充当了Java中的接口和抽象类,Dart中可以子类可以继承抽象类也可以实现抽象类接口。由于Dart中没有interface关键字所以定义接口时推荐使用抽象类,只是子类实现时不是使用extends而是使用implements

1. 抽象类

abstract class Fruits{
  String taste();
}

class Apple extends Fruits{
  
  String name;

  Apple(String this.name);

  @override
  String taste() {
    return "${name}苹果又甜又脆";
  }
}

//使用
Fruits fruits = new Apple("红富士");

print(fruits.taste());

//输出
红富士苹果又甜又脆

2. 接口

接口使用implements关键字而不是extends

abstract class Fruits{
  String taste();
}

class Apple implements Fruits{
  
  String name;

  Apple(String this.name);

  @override
  String taste() {
    return "${name}苹果又甜又脆";
  }
}

class Durian implements Fruits{
  @override
  String taste() {
    return '榴莲味道臭臭的但吃起来香';
  }
}

//使用
Fruits fruits = new Apple("烟台");
print(fruits.taste());

fruits = new Durian();
print(fruits.taste());

//输出
烟台苹果又甜又脆
榴莲味道臭臭的但吃起来香

使用implements关键字实现和extends继承,有什么区别?答案是,如果是用implements的话,那么接口中的所有方法子类都必须要复写。如果使用extends则只需要复写抽象方法即可。由此可以说明以下两点:

  1. 一个类到底是接口还是抽象类还是普通类,得看子类使用的是extends继承还是implements实现。
  2. 抽象类中可以有抽象方法,也可以有非抽象方法,什么样的方法是抽象方法?没有方法体的方法就是抽象方法。

注意,Dart与Java一样,只可以多实现不可以多继承。

3. mixins混合类

混合类其实是一个类似多继承的这么一个功能。为什么说类似多继承?因为从代码上看,它确实很像多继承。但使用mixins还有以下几个条件:

  1. 做为mixins的类只能继承自Object,不能继承其他类。
  2. 做为mixins的类不能有构造函数。
  3. 一个类可以mixins多个mixins类。
  4. mixins绝不是继承,也不是接口,而是Dart语言的一种全新的特性。
class Persion{
    void work(){
      print('人类都需要工作');
    }
}


class ET{
  void address(){
    print('外星人生活在其他星球');
  }
}

//mixins混合类。
class A with Persion, ET {}

//使用
var a = new A();
//混合类a即有Persion的方法又有ET的方法。其实就是class A,把这两个类给混合在了一起。
a.work();  
a.address();

//输出
人类都需要工作
外星人生活在其他星球

对混合类使用is进行类型判断的时候,会满足它所混合的所有类。

var a = new A();

print(a is Persion);
print(a is ET);

//输出
true
true

五、泛型

Dart中的泛型与Java中的泛型在使用上基本没有什么区别。只是有一点暂时不是很清楚,那就是不知道Dart中有没有类型擦除的概念。写demo是发现使用泛型后传入不同类型的数据在运行时会报错,不知道这是不是意味着Dart语言没有类型擦除。关于类型擦除以后再来研究,以后再来补齐这里的资料。

六、库

每一个.dart文件就是一个库。

1. 系统库

import 'dart:convert';
import 'dart:io';

2. 自定义库

impot 'lib/Persion.dart';

3. 三方库

Pub包管理系统中的库。

三方库的使用方法有以下几步:

  1. 需要在自己的项目的根目录中创建一个pubspec.yaml文件。

  2. 在pubspec.yaml文件中配置三方库的名称、描述、依赖等信息。

  3. 运行 pub get 命令将三方库下载到本地。

  4. 在项目中要使用的.dart文件中引入三方库,例如:

    import 'package:http/http.dart' as http;
    

4. 库的重命名

在导入的不同的库中存在相同名称的类时,直接使用类将会报错,因为编译器不知道你要使用的是哪个类,这时就需要用到库的重命名功能(导包时使用as为库重命名)。

import 'persion1.dart';
import 'persion1.dart' as p2;

main(){
    //构建persion1库中的Persion对象。
    Persion persion = new Persion();
    
    //构建persion2库中的Persion对象。
    p2.Persion persion2 = p2.Persion();
}

七、同步异步

调用异步方法要使用await关键字,而await关键字必须在async的方法中使用。async就是把方法变成异步方法,await就是等待异步方法执行完成。

main(List<String> args) async {
  var reqServer = await HttpServer.bind('192.168.0.100', 8080);
  print('服务已启动');
  await for (HttpRequest req in reqServer) {
    handleMessage(req);
  }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章