Dart快速入门

前言:

       最近学习flutter,发现怎么都绕不过dart, 于是就学习了一下dart,在此做个总结,本章节只讲跟Java不同的地方, 相同的地方一笔带过。

1、变量定义

main() {
    // 基本类型
    var a = 10;   // 可变类型,和JavaScript里面一样, 类型会自动转换
    var aa = "aaaaaa";
    var aaa = true;
    int b = 10;
    String c = "hello";
    dynamic d = "aaaaa";  // 跟var一样
    dynamic e = 10;
    dynamic f = 10.0;
    bool is = true;
    final String g = "aaa"; // 赋值后就不能改变
    final h = 10;     // 赋值为整型, 不写类型表示可以赋值为各种类型
    static const i = "aaa"; // 必须是static, 否则会报错,const必须直接被初始化成常量
    num j = 3; // 数字类型, 无论是整型还是小数都可以
    String k = "aaa"; // 跟Java声明变量一样

    // List的操作
    List<Map<String, String>> list = new List();
    Map<String, String> map = new Map();
    map['a'] = "aaa";
    map['b'] == "bbb";
    list.add(map);
    String name = map['a'];

    var map = new Map();
    map['name'] = 'zhangsan';
    map['age'] = 10;
    Map m = new Map();
    m['a'] = 'a';

    var arr = [1, 2, 3, 4, 5];
    List<String> arr2 = ['hello', 'world', "123", "456"];
    List<dynamic> arr3 = [1, true, 'haha', 1.0];

    // 声明方法和Java一样
    StringBuffer sb = new StringBuffer();
    sb.write("a");  // 相当于Java的append()
    print(sb.toString());
}

在Dart中一切都是对象,都继承于Object,例如整型转字符串: int a = 3;     String b = a.toString();

Dart是强类型语言,但是它又兼容JavaScript的var,类型可以自己推断, Dart支持泛型

Dart没有public、protected、private等关键字,如果一个变量以下划线开头表示变量私有

Dart变量可以以字母开头,由字母数字下划线组成

2、函数

Dart声明方法和Java的类似,它可以不指明返回值, 但是还是推荐指明,当方法只有一条语句,并且return这条语句的时候可以用=>来代替.

不论在Dart还是Flutter中,都有一个main函数,它是应用的入口函数,返回值是void,还有一个可选参数,参数类型是List<String>

所有的函数都有返回值,如果没有指定return语句,那么该函数的返回值为null

// 声明返回值
int add(int a, int b) {
    return a + b;
}

// 不声明返回值, 但是不推荐
add2(int a, int b) {
    return a + b;
}

// 只有一条语句,并且返回这条语句
add3(int a, int b) => a + b;

// 只有一条语句,并且返回这条语句, 变量类型可以不写, 接收多种类型
add3(a, b) => a + b;

// 中括号表示参数可以不传, 是可选参数
add4(int a, int b, [int c]) {
    
}

main() {
    print(add(1, 2));
    print(add2(1, 2));
    print(add3(1, 2));
}

函数其实可以作为一个对象传递给另一个对象, 这个类似于oc里面的块代码

// dart中可以通过$加变量名来显示变量的值
printString(int a) {
    print("$a");
}

main() {
    List<String> list = ["aaa", "bbb", "ccc"];
    // 列表对象都有一个forEach方法, 里面需要传一个方法,意思是把每一个元素取出来传给这个方法
    list.forEach(printString);

    var fun1 = printString;
    fun1("hhhhhhhhhhh"); // 相当于引用了printString方法

    // fun2指向了一个匿名方法,这个匿名方法有一句代码
    var fun2 = (int a) => print("a = $a");
    // 上面代码可以写成:
    var fun2 = (int a) {
        print("a = $a");
    }

    // 没有参数:
    var fun3 = () {
        print("aaaa");
    }
}

3、操作符

操作符大多数都跟Java一样,只有个别不一样, 现在我们看看有哪些不一样:

  // is运算符用于判断一个变量是不是某个类型的数据
  // is!则是判断变量不是某个类型的数据
  var s = "hello";
  print(s is String); // true
  var num = 6;
  print(num is! String); // true

  // ~/才是取整运算符,如果使用/则是除法运算,不取整
  int k = 1;
  int j = 2;
  print(k / j); // 0.5
  print(k ~/ j); // 0

  // as运算符类似于Java中的cast操作,将一个对象强制类型转换
  (emp as Person).teach();

  // ??=运算符 如果 ??= 运算符前面的变量为null,则赋值,否则不赋值
  var param1 = "hello", param2 = null;
  param1 ??= "world";
  param2 ??= "world";
  print("param1 = $param1"); // param1 = hello
  print("param2 = $param2"); // param2 = world
  
  // ?.运算符
  var str1 = "hello world";
  var str2 = null;
  print(str1?.length); // 11
  print(str2?.length); // null 
  print(str2.length); // 报错

.. 运算符:级联运算符,跟Java中的build模式特别像

class Person {
  eat() {
    print("I am eating...");
  }

  sleep() {
    print("I am sleeping...");
  }

  study() {
    print("I am studying...");
  }
}

main() {
  // 依次打印
  //  I am eating...
  //  I am sleeping...
  //  I am studying...
  new Person()..eat()
      ..sleep()
      ..study();
}

4、流程控制(if-else    switch  for   while等等都跟Java一样,唯独try-catch稍微有点不太一样)

    // 捕获所有异常
    try {
      List<Map<String, String>> list = new List();
      Map<String, String> map = new Map();
      map['a'] = "aaa";
      map['b'] == "bbb";
      list.add(map);
      String name = map['a'];
    }
    catch (e) {
      print(e.toString());
    } finally {
        
    }


// 捕获指定异常
try {
    1 ~/ 0;
} on IntegerDivisionByZeroException { // 捕获指定类型的异常
    print("error"); // 打印出error
} finally {
    print("over"); // 打印出over
}

5、类

class Person {
  String name;
  int age;
  String sex;
  Person(this.name, this.age, this.sex);
  sayHello() {
    print("hello, this is $name, I am $age years old, I am a $sex");
  }
}

Person类中有3个成员变量,一个构造方法和一个成员方法,看起来比较奇怪的是Person的构造方法,里面传入的3个参数都是this.xxx,而且没有大括号{}包裹的方法体,这种语法是Dart比较独特而简洁的构造方法声明方式,它等同于下面的代码:

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

     要调用Person类的成员变量或成员方法,可以用下面的代码:

var p = new Person("zhangsan", 20, "male");
p.sayHello(); // hello, this is zhangsan, I am 20 years old, I am a male
p.age = 50;
p.sex= "female";
p.sayHello(); // hello, this is zhangsan, I am 50 years old, I am a female

类除了有跟类名相同的构造方法外,还可以添加命名的构造方法,如下代码所示:

class Point {
  num x, y;
  Point(this.x, this.y);
  // 类的命名构造方法, 方法名可以自己随便取
  Point.origin() {
    x = 0;
    y = 0;
  }
}

main() {
  // 调用Point类的命名构造方法origin()
  var p = new Point.origin();
  var p2 = new Point(1, 2);
}

跟Java一样,dart也是用extends关键字来继承:如果一个类只有命名的构造方法,在继承时需要注意,如下代码:

class Human {
  String name;
  Human.fromJson(Map data) {
    print("Human's fromJson constructor");
  }
}

class Man extends Human {
  Man.fromJson(Map data) : super.fromJson(data) {
    print("Man's fromJson constructor");
  }
}

由于Human类没有默认构造方法,只有一个命名构造方法fromJson,所以在Man类继承Human类时,需要调用父类的fromJson方法做初始化,而且必须使用Man.fromJson(Map data) : super.fromJson(data)这种写法,而不是像Java那样将super写到花括号中。

类里面的set get方法:

class Persion {
  int x, y;
  num a, b;
  Persion() {}  // 经测试类里面只能有一个这种构造函数,它不能与下面带参的构造函数共存
  //  Persion(this.x, this.y);  // 有我没上面的

  Persion.origial(Map<String, String> map) { // 可以和上面的任意一个构造函数共存
    x = 10;
    y = 12;
  }

  // 这是get方法的固定写法, getX函数名是自己取的
  // int 表示返回值, get表示这是get方法, getx是函数名, 后面是函数的实现
  int get getx => x + y;
  int get gety {    // 等同于上面的写法
    return x+y;
  }

  // 这是set方法的固定写法, setX函数名是自己取的
  // 函数返回null, set表示这是set方法, setX是函数名, 后面是函数的实现
  set setX(int xx) => x = xx - y;
  set setY(int yy) {   // 等同于上面
    y = xx - y;
  }
}

抽象类和抽象方法:跟Java差不多

使用abstract修饰一个类,则这个类是抽象类,这个类必须被继承,抽象类中可以有抽象方法和非抽象方法,抽象方法没有方法体,需要子类去实现

abstract class Doer {
  // 抽象方法,没有方法体,需要子类去实现
  void doSomething();
  // 普通的方法
  void greet() {
    print("hello world!");
  }
}

class EffectiveDoer extends Doer {
  // 实现了父类的抽象方法
  void doSomething() {
    print("I'm doing something...");
  }
}

枚举

和Java类似

enum Color { red, green, blue }

with的用法: 

class A {
  a() {
    print("A's a()");
  }
}

class B {
  b() {
    print("B's b()");
  }
}

// 使用with关键字,表示类C是由类A和类B混合而构成
class C = A with B;

main() {
  C c = new C();
  c.a(); // 输出:A's a()
  c.b(); // 输出:B's b()
}

静态成员和静态方法:

// 跟Java一样,静态成员变量和方法可以用类名直接访问

// 类的静态成员变量和静态成员方法
class Cons {
  static const name = "zhangsan";
  static sayHello() {
    print("hello, this is ${Cons.name}");
  }
}

main() {
  Cons.sayHello(); // hello, this is zhangsan
  print(Cons.name); // zhangsan
}

注意: 类实例化变量的时候可以省掉前面的new, 直接"类名()"来实例化

6、泛型(和Java类似)

7、方法的命名参数

printName({String name}) {
  print("hello, my name is $name");
}

printName2({name: String}) {
  print("hello, my name is $name");
}

main() {
  // 打印 hello, my name is dongjie
  printName(name: 'dongjie');

  // 打印 hello, my name is xiaoli
  printName2(name: 'xiaoli');
}

从上面例子中可以看到,定义命名参数时,你可以以 {type paramName} 或者 {paramName: type} 两种方式声明参数,而调用命名参数时,需要以 funcName(paramName: paramValue) 的形式调用。

命名参数的参数并不是必须的,所以上面的代码中,如果调用printName()不带任何参数,也是可以的,只不过最后打印出来的结果是:hello, my name is null,在Flutter开发中,你可以使用@required注解来标识一个命名参数,这代表该参数是必须的,你不传则会报错

7、匿名方法

匿名方法的定义:

(参数1,参数2,....){

	方法体...

 	return 返回值

 }
void main(List<String> args) {
  var func = () {
    print("Hello");
  };
  func();


  var func1 = (str) {
    print("Hello-------$str");
  };
  func1("huangxiaoguo");


  // 通过()进行调用,不推荐使用
  (() {
    print("通过()进行调用,不推荐使用");
  })();


//匿名方法传参
  var list2 = ['h', 'e', 'l', 'l', 'o'];
  print(listTimes(list2, (str) {
    return str * 3;
  }));
}

List listTimes(List list, String times(str)) {
  for (var i = 0; i < list.length; i++) {
    list[i] = times(list[i]);
  }
  return list;
}

 输出:

Hello 

Hello-------huangxiaoguo 

通过()进行调用,不推荐使用 

[hhh, eee, lll, lll, ooo]

8、Dart引用外部文件

如果你要使用的类或者代码在其他的文件中,则需要把它引进来,通过import

import 'package:flutter/material.dart';
import './util.dart';
import '../dart:html';   // 两个点代表上一级

可以使用as关键字为导入的某个包设置一个前缀,或者说别名,比如下面的代码:

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

// Uses Element from lib1.
Element element1 = Element();

// Uses Element from lib2.
lib2.Element element2 = lib2.Element();

上面的没懂? 看个例子:我引用了http库,调用里面的方法:

也可以在导入包时使用show hide关键字来导入某个包中的部分功能,比如下面的代码:

// 只导入foo
import 'package:lib1/lib1.dart' show foo;

// 导入除了foo的所有其他部分
import 'package:lib2/lib2.dart' hide foo;

导入包时使用deferred as可以让这个包懒加载,懒加载的包只会在该包被使用时得到加载,而不是一开始就加载,比如下面的代码:

import 'package:greetings/hello.dart' deferred as hello;

9、异步操作

Dart提供了async await等异步操作,这种异步操作在Flutter开发中会经常遇到,比如网络或其他IO操作。

async和await往往是成对出现的,如果一个方法中有耗时的操作,你需要将这个方法设置成async,并给其中的耗时操作加上await关键字,如果这个方法有返回值,你需要将返回值塞到Future中并返回:

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

Future<String> getNetData() async{
  http.Response res = await http.get("http://www.baidu.com");
  return res.body;
}

main() {
  getNetData().then((str) {
    print(str);
  });
}

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值