关于flutter:Dart基础知识汇总

1 介绍

Dart是由谷歌开发的计算机编程语言,它能够被用于web、服务器、挪动利用 和物联网等畛域的开发。

Dart诞生于2011年,号称要取代JavaScript。然而过来的几年中始终不温不火。直到Flutter的呈现当初被人们从新器重。

要学Flutter的话咱们必须首先得会Dart。

官网:https://dart.dev/

2 环境搭建

要在咱们本地开发Dart程序的话首先须要装置Dart SDK。

官网文档:https://dart.dev/get-dart。

windows环境

http://www.gekorm.com/dart-wi…。

mac环境

参考上一篇文章, Mac搭建Flutter+Dart开发环境。

3 开发工具

Dart的开发工具有很多: IntelliJ IDEA 、 WebStorm、 Atom、VS Code等

这里咱们次要给大家解说的是如果在VS Code中配置Dart。

1 装置VS Code https://code.visualstudio.com/。

2 找到VS Code插件装置dart。

3 找到VS Code插件装置code runner Code Runner 能够运行咱们的文件。

4 变量 常量 命名规定

变量

dart是一个弱小的脚本类语言,能够不事后定义变量类型 ,主动会类型推倒。

dart中定义变量能够通过var关键字能够通过类型来申明变量。

留神:var 后就不要写类型,写了类型不要var 两者都写 var a int = 5; 报错。

var str = 'this is var';
String str = 'this is var';
int str = 123;

常量

final 和 const修饰符

const值不变 一开始就得赋值。

final 能够开始不赋值 只能赋一次 ; 而final不仅有const的编译时常量的个性,最重要的它是运行时常量,并且final是惰性初始化,即在运行时第一次应用前才初始化。

永远不改量的量,请应用final或const润饰它,而不是应用var或其余变量类型。

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
const bar = 1000000; // Unit of pressure (dynes/cm2)
const double atm = 1.01325 * bar; // Standard atmosphere

命名规定

1、变量名称必须由数字、字母、下划线和美元符($)组成。

2、留神:标识符结尾不能是数字

3、标识符不能是保留字和关键字。

4、变量的名字是辨别大小写的如: age和Age是不同的变量。在理论的使用中,也倡议,不要用一个单词大小写辨别两个变量。

5、标识符(变量名称)肯定要见名思意 :变量名称倡议用名词,办法名称倡议用动词。

5 数据类型

罕用数据类型:

Numbers(数值)

int 必须是整型

double 既能够是整型 也可是浮点型

Strings(字符串)

String

字符串定义的几种形式

var str1 = 'this is str1';

var str2 = "this is str2";

String str1 = 'this is str1';

String str2 = "this is str2";

/// 三个'''或者三个"""能够多行
String str1 = '''
this is str1
this is str1
this is str1
''';

String str = """
this is str1
this is str1
this is str1
""";

字符串的拼接

String str1 = '你好';

String str2 = 'Dart';

print("$str1 $str2");

print(str1 + str2);

print(str1 +" "+ str2);

Booleans(布尔)

bool

List(数组)

在Dart中,数组是列表对象,所以大多数人只是称它们为列表

List定义形式

var l1 = ['aaa','bbbb','cccc'];
var l2 = <String>[];

Maps(字典)

通常来说,Map 是一个键值对相干的对象。 键和值能够是任何类型的对象。每个 键只呈现一次, 而一个值则能够呈现屡次

Map定义形式

var person = {
    "name":"张三",
    "age":20,
    "work":["程序员","送外卖"]
};
print(person["name"]);

var p = new Map();
p["name"] = "李四";
p["age"] = 22;
p["work"] = ["程序员","送外卖"];
print(p);

类型判断

var str=123;
if(str is String) {
  print('是string类型');
}
else if(str is int) {
  print('int');
} else {
  print('其余类型');
}

6 运算符 条件判断 类型转换

算术运算符

加减乘除取余取整

int a = 13;
int b = 5;
print(a + b);   //加
print(a - b);   //减
print(a * b);   //乘
print(a / b);   //除
print(a % b);   //取余
print(a ~/ b);  //取整

++ —

示意自增 自减 1

在赋值运算外面 如果++ — 写在后面 这时候先运算 再赋值,如果++ –写在前面 先赋值后运行运算

var a = 10;
var b = a--;
print(a);  //9
print(b);  //10

var a = 10;
var b = ++a;
print(a);  //11
print(b);  //11

关系运算符

int a = 5;
int b = 3;
print(a == b);   //判断是否相等
print(a != b);   //判断是否不等
print(a > b);    //判断是否大于
print(a < b);    //判断是否小于
print(a >= b);   //判断是否大于等于
print(a <= b);   //判断是否小于等于

逻辑运算符

! 取反

bool flag = false;
print(!flag);

&& 并且: 全副为true的话值为true 否则值为false

bool a = true;
bool b = true;
print(a && b);

|| 或者:全为false的话值为false 否则值为true

bool a = false;
bool b = false;
print(a || b);

赋值运算符

根底赋值运算符 = ??=

int a = 10;
int b = 3;
print(a);
int c = a + b;   //从右向左

int b;
b ??= 23;   // 示意如果b为空的话把 23赋值给b
print(b);

复合赋值运算符 += -= *= /= %= ~/=

var a = 13;
a += 10;   //示意 a = a + 10
print(a);

条件表达式

if else switch case

// 判断一个人的问题 如果大于60 显示及格   如果大于 70显示良好  如果大于90显示优良
var score = 41;
if(score > 90) {
  print('优良');
} else if(score > 70) {
  print('良好');
} else if(score >= 60) {
  print('及格');
} else {
  print('不及格');
}

var sex = "女";
switch(sex) {
  case "男":
       print('性别是男');
       break;
  case "女":
       print('性别是女');
       break;
  default:
       print('传入参数谬误');
       break;
  }

三目运算符

bool flag = false;
String c = flag ? '我是true' : '我是false';
print(c);

?? 运算符

var a = 22;
var b = a ?? 10;
print(b);

类型转换

Number与String类型之间的转换

Number类型转换成String类型 toString()

String类型转成Number类型 int.parse()

String str = '123';
var myNum = int.parse(str);
print(myNum is int);

String str = '123.1';
var myNum = double.parse(str);
print(myNum is double);

//报错
String price = '';
var myNum = double.parse(price);
print(myNum);
print(myNum is double);

// try  ... catch
String price = '';
try {
    var myNum=double.parse(price);
    print(myNum);
} catch(err) {
    print(0);
} 

var myNum = 12;
var str = myNum.toString();
print(str is String);

其余类型转换成Booleans类型

isEmpty:判断字符串是否为空

var str = '';
if(str.isEmpty) {
  print('str空');
} else {
  print('str不为空');
}

var myNum;
if(myNum == 0) {
   print('0');
} else {
  print('非0');
}

var myNum;
if(myNum == null) {
   print('空');
} else {
  print('非空');
}

var myNum = 0/0;
print(myNum);
if(myNum.isNaN) {
  print('NaN');
}

7 循环遍历

for循环

根本语法

第一步,申明变量int i = 1;

第二步,判断i <=100

第三步,print(i);

第四步,i++

第五步 从第二步再来,直到判断为false

for (int i = 1; i <= 100; i++) {   
     print(i);
}
 
//打印List  ['张三','李四','王五'] 外面的内容
var list = ['张三','李四','王五'];
for(var i = 0; i < list.length; i++) {
  print(list[i]);
}

while循环

语法格局:

while(表达式/循环条件){

}

do{

语句/循环体

}while(表达式/循环条件);

留神: 1、最初的分号不要遗记

2、循环条件中应用的变量须要通过初始化

3、循环体中,应有完结循环的条件,否则会造成死循环。

//求1+2+3+4 ...+100的和
int i = 1;
var sum = 0;
while(i <= 100) {
   sum += i;
   i++;
}
print(sum);

int i = 1;
var sum = 0;
do{
  sum += i;
  i++;
}while(i <= 100);
print(sum);

break和continue

break语句性能:

1、在switch语句中使流程跳出switch构造。

2、在循环语句中使流程跳出以后循环,遇到break 循环终止,前面代码也不会执行

强调:

1、如果在循环中曾经执行了break语句,就不会执行循环体中位于break后的语句。

2、在多层循环中,一个break语句只能向外跳出一层

break能够用在switch case中 也能够用在 for 循环和 while循环中

continue语句的性能:

【注】只能在循环语句中应用,使本次循环完结,即跳过循环体重上面尚未执行的语句,接着进行下次的是否执行循环的判断。

continue能够用在for循环以及 while循环中,然而不倡议用在while循环中,不小心容易死循环

// 如果i等于4的话跳过
for(var i = 1; i <= 10; i++) {
   if(i == 4) {
      continue;  /*跳过以后循环体 而后循环还会继续执行*/
   }
   print(i);
}
  
// 如果 i等于4的话跳出循环
for(var i = 1; i <= 10; i++) {
    if(i == 4) {
       break;  /*跳出循环体*/
    }
    print(i);
}

8 List

List外面罕用的属性和办法:

罕用属性

length 长度

reversed 翻转

isEmpty 是否为空

isNotEmpty 是否不为空

var myList = ['香蕉','苹果','西瓜'];
print(myList.length);
print(myList.isEmpty);
print(myList.isNotEmpty);
print(myList.reversed);  //对列表倒序排序
var newMyList = myList.reversed.toList();
print(newMyList);

罕用办法

add 减少

addAll 拼接数组

indexOf 查找 传入具体值

remove 删除 传入具体值

removeAt 删除 传入索引值

fillRange 批改

insert(index,value); 指定地位插入

insertAll(index,list) 指定地位插入List

toList() 其余类型转换成List

join() List转换成字符串

split() 字符串转化成List

forEach

map

where

any

every

// List外面的办法:
var myList = ['香蕉','苹果','西瓜'];
myList.add('桃子');   //减少数据  减少一个
myList.addAll(['桃子','葡萄']);  //拼接数组
print(myList);
print(myList.indexOf('苹x果'));    //indexOf查找数据 查找不到返回-1  查找到返回索引值
myList.remove('西瓜');
myList.removeAt(1);
print(myList);
  
var myList = ['香蕉','苹果','西瓜'];
myList.fillRange(1, 2, 'aaa');  //批改
myList.fillRange(1, 3, 'aaa');  
myList.insert(1, 'aaa');      //插入  一个
myList.insertAll(1, ['aaa', 'bbb']);  //插入 多个
print(myList);

var myList = ['香蕉','苹果','西瓜'];
var str = myList.join('-');   //list转换成字符串
print(str);
print(str is String);  //true

var str = '香蕉-苹果-西瓜';
var list = str.split('-');
print(list);
print(list is List);

9 Set

用它最次要的性能就是去除数组反复内容

Set是没有程序且不能反复的汇合,所以不能通过索引去获取值

var s = new Set();
s.add('香蕉');
s.add('苹果');
s.add('苹果');
print(s);   // {香蕉, 苹果}
print(s.toList()); 

var myList = ['香蕉','苹果','西瓜','香蕉','苹果','香蕉','苹果'];
var s = new Set();
s.addAll(myList);
print(s);
print(s.toList());

10 Map

映射(Map)是无序的键值对:

罕用属性

keys 获取所有的key值

values 获取所有的value值

isEmpty 是否为空

isNotEmpty 是否不为空

Map person = {
    "name":"张三",
    "age":20
};

var m = new Map();
m["name"] = "李四";
print(person);
print(m);

Map person = {
    "name":"张三",
    "age":20,
    "sex":"男"
};
print(person.keys.toList());
print(person.values.toList());
print(person.isEmpty);
print(person.isNotEmpty);

罕用办法

remove(key) 删除指定key的数据

addAll({…}) 合并映射 给映射内减少属性

containsValue 查看映射内的值 返回true/false

forEach

map

where

any

every

Map person = {
    "name":"张三",
    "age":20,
    "sex":"男"
};
person.addAll({
    "work":['敲代码', '送外卖'],
    "height":160
});
print(person);
person.remove("sex");
print(person);
print(person.containsValue('张三'));

11 forEach map where any every

forEach

List myList = ['香蕉', '苹果', '西瓜'];
for(var i = 0; i < myList.length; i++) {
    print(myList[i]);
}

for(var item in myList) {
    print(item);
}

myList.forEach((value) {
    print("$value");
});

var s = new Set();
s.addAll([1,222,333]);
s.forEach((value) => print(value));

Map person = {
    "name":"张三",
    "age":20
};
person.forEach((key,value){            
    print("$key---$value");
});

map

List myList = [1, 3, 4];      
var newList = myList.map((value) {
     return value * 2;
});
print(newList.toList());

where

List myList = [1, 3, 4, 5, 7, 8, 9];
var newList = myList.where((value) {
     return value > 5;
});
print(newList.toList());

any

List myList = [1, 3, 4, 5, 7, 8, 9];
var f = myList.any((value) {   //只有汇合外面有满足条件的就返回true
     return value > 5;
});
print(f);

every

List myList = [1, 3, 4, 5, 7, 8, 9];
var f = myList.every((value) {   //每一个都满足条件返回true  否则返回false
     return value > 5;
});
print(f);

12 办法的定义 变量 办法的作用域

内置办法/函数

print();

自定义办法

自定义办法的根本格局:

返回类型 办法名称(参数1,参数2,…){

办法体

return 返回值;

}

void printInfo(){
  print('我是一个自定义办法');
}

int getNum(){
  var myNum = 123;
  return myNum;
}

String printUserInfo(){
  return 'this is str';
}

List getList(){
  return ['111','2222','333'];
}

void main(){
  print('调用零碎内置的办法');
  printInfo();
  
  var n = getNum();
  print(n);
  
  print(printUserInfo());
  print(getList());
  print(getList());
  

  //演示办法的作用域
  void xxx(){
      aaa(){
          print(getList());
          print('aaa');
      }
      aaa();
  }

  // aaa();  谬误写法 
  xxx();  //调用办法
}

13 办法传参 、可选参数、默认参数、命名参数 、办法作为参数

办法传参

// 定义一个办法 求1到这个数的所有数的和      60    1+2+3+。。。+60
int sumNum(int n){
  var sum=0;
  for(var i = 1; i <= n; i++){
    sum+=i;
  }
  return sum;
} 
var n1 = sumNum(5);
print(n1);
var n2 = sumNum(100);
print(n2);

// 定义一个办法而后打印用户信息
String printUserInfo(String username, int age){  //行参
  return "姓名:$username---年龄:$age";
}
print(printUserInfo('张三',20)); //实参

可选参数

String printUserInfo(String username, [int age]){  //行参
  if(age != null){
    return "姓名:$username---年龄:$age";
  }
  return "姓名:$username---年龄窃密";
}
print(printUserInfo('张三', 21)); //实参
print(printUserInfo('张三'));

默认参数

String printUserInfo(String username, [String sex = '男', int age]){  //行参
  if(age != null){
    return "姓名:$username---性别:$sex--年龄:$age";
  }
  return "姓名:$username---性别:$sex--年龄窃密";
}
print(printUserInfo('张三'));
print(printUserInfo('小李', '女'));
print(printUserInfo('小李', '女', 30));

命名参数

String printUserInfo(String username, {int age, String sex = '男'}){  //行参
  if(age != null){
    return "姓名:$username---性别:$sex--年龄:$age";
  }
  return "姓名:$username---性别:$sex--年龄窃密";
}
print(printUserInfo('张三', age:20, sex:'未知'));

办法作为参数

var fn = () {
  print('我是一个匿名办法');
};      
fn();

//办法
fn1(){
  print('fn1');
}

//办法
fn2(fn){
  fn();
}

//办法传参调用fn2这个办法 把fn1这个办法当做参数传入
fn2(fn1);

14 箭头函数 函数的互相调用

箭头函数

/*需要:应用forEach打印上面List外面的数据*/
List list = ['苹果', '香蕉', '西瓜'];
list.forEach((value){
  print(value);
});

list.forEach((value) => print(value));

list.forEach((value) => {
  print(value)
});


/*需要:批改上面List外面的数据,让数组中大于2的值乘以2*/
List list = [4, 1, 2, 3, 4];
var newList = list.map((value){
  if(value > 2){
    return value * 2;
  }
  return value;
});
print(newList.toList());

var newList = list.map((value) => value > 2 ? value * 2 : value);
print(newList.toList());

函数的互相调用

/*
需要:1、定义一个办法isEvenNumber来判断一个数是否是偶数  
     2、定义一个办法打印1-n以内的所有偶数
*/
// 定义一个办法isEvenNumber来判断一个数是否是偶数  
bool isEvenNumber(int n){
  if(n % 2 == 0){
    return true;
  }
  return false;
}

printNum(int n){
  for(var i = 1; i <= n; i++){
    if(isEvenNumber(i)){
      print(i);
    }
  }
}
printNum(10);

15 闭包

1、全局变量特点: 全局变量常驻内存、全局变量净化全局

2、局部变量的特点: 不常驻内存会被垃圾机制回收、不会净化全局

想实现的性能:1.常驻内存 2.不净化全局

产生了闭包, 闭包能够解决这个问题…..

闭包: 函数嵌套函数, 外部函数会调用内部函数的变量或参数, 变量或参数不会被零碎回收(不会开释内存)

闭包的写法: 函数嵌套函数,并return 外面的函数,这样就造成了闭包。

/*全局变量*/
var a = 123;

void main(){
  print(a);
  fn(){
    a++;
    print(a);
  }
  fn();
  fn();
  fn();

  // 局部变量
  printInfo(){
    var myNum = 123;
    myNum++;
    print(myNum);
  }
  printInfo();
  printInfo();
  printInfo();
  
  // 闭包
  fn(){
    var a = 123;  /*不会净化全局   常驻内存*/
    return(){            
      a++;            
      print(a);
     };        
  }     
  var b = fn();    
  b();
  b();
  b();
}

16 面向对象的介绍 以及内置对象

面向对象编程(OOP)的三个基本特征

封装

封装是对象和类概念的次要个性。封装,把客观事物封装成形象的类,并且把本人的局部属性和办法提供给其余对象调用, 而一部分属性和办法则暗藏。

继承

面向对象编程 (OOP) 语言的一个次要性能就是“继承”。继承是指这样一种能力:它能够应用现有类的性能,并在无需从新编写原来的类的状况下对这些性能进行扩大。

多态

容许将子类类型的指针赋值给父类类型的指针, 同一个函数调用会有不同的执行成果 。

Dart所有的货色都是对象,所有的对象都继承自Object类。

Dart是一门应用类和单继承的面向对象语言,所有的对象都是类的实例,并且所有的类都是Object的子类

一个类通常由属性和办法组成。

List list = new List();
list.isEmpty;
list.add('香蕉');
list.add('香蕉1');

Map m = new Map();
m["username"] = "张三";
m.addAll({"age":20});
m.isEmpty;

Object a = 123;
Object v = true;
print(a);
print(v);

17 创立自定义类应用类

Dart是一门应用类和单继承的面向对象语言,所有的对象都是类的实例,并且所有的类都是Object的子类

class Person {
  String name = "张三";
  int age = 23;
  void getInfo(){
    
      // print("$name----$age");
      print("${this.name}----${this.age}");
  }
  void setInfo(int age){
    this.age = age;
  }
}
void main(){

  // 实例化
  Person p1 = new Person();
  print(p1.name);
  p1.setInfo(28);
  p1.getInfo();
}

自定义类的默认构造函数

class Person {
  String name = '张三';
  int age = 20; 
  
  //默认构造函数
  Person(){
    print('这是构造函数外面的内容  这个办法在实例化的时候触发');
  }
  void printInfo(){   
    print("${this.name}----${this.age}");
  }
}

// 张三  李四  王五
class Person {
  String name;
  int age; 
  
  //默认构造函数
  Person(String name, int age){
    this.name = name;
    this.age = age;
  }
  void printInfo(){   
    print("${this.name}----${this.age}");
  }
}

class Person {
  String name;
  int age; 
  
  //默认构造函数的简写
  Person(this.name, this.age);
  void printInfo(){   
    print("${this.name}----${this.age}");
  }
}

void main(){
  Person p1 = new Person('张三',20);
  p1.printInfo();

  Person p2 = new Person('李四',25);
  p2.printInfo();
}

自定义类的命名构造函数

dart外面构造函数能够写多个

class Person {
  String name;
  int age; 
  
  //默认构造函数的简写
  Person(this.name, this.age);
  
  Person.now(){
    print('我是命名构造函数');
  }

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

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

void main(){
  var d = new DateTime.now();   //实例化DateTime调用它的命名构造函数
  print(d);
  
  Person p1 = new Person('张三', 20);   //默认实例化类的时候调用的是 默认构造函数
  
  Person p1 = new Person.now();   //命名构造函数
  
  Person p1 = new Person.setInfo('李四',30);
  p1.printInfo(); 
}

把类独自抽离成一个模块

// 将Person类文件Person.dart放到lib文件夹外面
import 'lib/Person.dart';

void main(){
  Person p1 = new Person.setInfo('李四1', 30);
  p1.printInfo(); 
}

公有办法和公有属性

Dart和其余面向对象语言不一样,Data中没有 public private protected这些拜访润饰合乎

咱们能够应用_把一个属性或者办法定义成公有。

class Animal {
  String _name;   //公有属性
  int age; 
  
  //默认构造函数的简写
  Animal(this._name, this.age);

  void printInfo(){   
    print("${this._name}----${this.age}");
  }

  String getName(){ 
    return this._name;
  } 
  void _run(){
    print('这是一个公有办法');
  }

  execRun(){
    this._run();  //类外面办法的互相调用
  }
}

import 'lib/Animal.dart';

void main(){
 
 Animal a = new Animal('小狗', 3);
 print(a.getName());
 a.execRun();   //间接的调用公有办法
}

类中的getter和setter修饰符的用法

class Rect {
  int height;
  int width;
  
  getArea(){
    return this.height * this.width;
  } 
}

class Rect {
  num height;
  num width; 
  
  Rect(this.height, this.width);
  area(){
    return this.height * this.width;
  }
}

void main(){
  Rect r = new Rect(10, 4);
  print("面积:${r.area()}");   
}

class Rect {
  num height;
  num width;   
  Rect(this.height, this.width);
  get area{
    return this.height * this.width;
  }
}

void main(){
  Rect r = new Rect(10, 2);
  print("面积:${r.area}");      //留神调用间接通过拜访属性的形式拜访area
}

class Rect {
  num height;
  num width; 
  
  Rect(this.height, this.width);
  get area{
    return this.height * this.width;
  }
  set areaHeight(value){
    this.height = value;
  }
}

void main(){
  Rect r = new Rect(10, 4);
  // print("面积:${r.area()}");   
  r.areaHeight = 6;
  print(r.area);
}

类中的初始化列表

咱们也能够在构造函数体运行之前初始化实例变量

class Rect {
  int height;
  int width;
  Rect():height = 2, width = 10{
    print("${this.height}---${this.width}");
  }
  getArea(){
    return this.height * this.width;
  } 
}

void main(){
  Rect r = new Rect();
  print(r.getArea()); 
}

类中的动态成员 静态方法

Dart中的动态成员:

1、应用static 关键字来实现类级别的变量和函数

2、静态方法不能拜访非动态成员,非静态方法能够拜访动态成员

class Person {
  static String name = '张三';
  static void show() {
    print(name);
  }
}

main(){
  print(Person.name);
  Person.show();  
}

class Person {
  static String name = '张三';
  int age = 20;
  
  static void show() {
    print(name);
  }
  
  void printInfo(){  /*非静态方法能够拜访动态成员以及非动态成员*/
    print(name);  //拜访动态属性
    print(this.age);  //拜访非动态属性
    show();   //调用静态方法
  }
  
  static void printUserInfo(){//静态方法
    print(name);   //动态属性
    show();        //静态方法
    
    // print(this.age);     //静态方法没法拜访非动态的属性
    // this.printInfo();    //静态方法没法拜访非动态的办法
    // printInfo();
  }
}

main(){
  print(Person.name);
  Person.show(); 
  
  Person p = new Person();
  p.printInfo(); 
  Person.printUserInfo();
}

对象操作符

? 条件运算符 (理解)

as 类型转换

is 类型判断

.. 级联操作 (连缀) (记住)

class Person {
  String name;
  num age;
  Person(this.name, this.age);
  void printInfo() {
    print("${this.name}---${this.age}");  
  }
}

main(){ 
  Person p;
  p?.printInfo();
  
  Person p = new Person('张三', 20);
  p?.printInfo();
  
  Person p = new Person('张三', 20);
  if(p is Person){
    p.name = "李四";
  } 
  p.printInfo();
  print(p is Object);

  var p1;
  p1 = '';
  p1 = new Person('张三1', 20);

    // // p1.printInfo();
    // (p1 as Person).printInfo();

  Person p1 = new Person('张三1', 20);
  p1.printInfo();
  p1.name = '张三222';
  p1.age = 40;
  p1.printInfo();
  
  Person p1 = new Person('张三1', 20);
  p1.printInfo();
  p1..name = "李四"
    ..age = 30
    ..printInfo();
}

类的继承-简略继承

1、子类应用extends关键词来继承父类

2、子类会继承父类外面可见的属性和办法 然而不会继承构造函数

3、子类能复写父类的办法 getter和setter

class Person {
  String name = '张三';
  num age = 20; 
  void printInfo() {
    print("${this.name}---${this.age}");  
  } 
}

class Web extends Person {

}

main(){
  Web w = new Web();
  print(w.name);
  w.printInfo();
}

super关键词的应用

class Person {
  String name;
  num age; 
  Person(this.name, this.age);
  void printInfo() {
    print("${this.name}---${this.age}");  
  }
}

class Web extends Person {
  Web(String name, num age) : super(name, age){

  }
}

main(){ 
  Person p = new Person('李四', 20);
  p.printInfo();

  Person p1 = new Person('张三', 20);
  p1.printInfo();

  Web w = new Web('张三', 12);
  w.printInfo();
}

实例化自类 给父类构造函数传参

class Person {
  String name;
  num age; 
  Person(this.name, this.age);
  Person.xxx(this.name, this.age);
  void printInfo() {
    print("${this.name}---${this.age}");  
  }
}

class Web extends Person {
  String sex;
  Web(String name, num age, String sex) : super.xxx(name, age){
    this.sex = sex;
  }
  run(){
   print("${this.name}---${this.age}--${this.sex}");  
  }
}

main(){ 
  Person p = new Person('李四', 20);
  p.printInfo();
  
  Person p1 = new Person('张三', 20);
  p1.printInfo();

  Web w = new Web('张三', 12, "男");
  w.printInfo();
  w.run();
}

实例化自类给命名构造函数传参

class Person {
  String name;
  num age; 
  Person(this.name, this.age);
  Person.xxx(this.name, this.age);
  void printInfo() {
    print("${this.name}---${this.age}");  
  }
}

class Web extends Person {
  String sex;
  Web(String name, num age, String sex) : super.xxx(name, age){
    this.sex = sex;
  }
  run(){
   print("${this.name}---${this.age}--${this.sex}");  
  }
}

main(){ 
  Person p = new Person('李四', 20);
  p.printInfo();
  
  Person p1 = new Person('张三', 20);
  p1.printInfo();

  Web w = new Web('张三', 12, "男");
  w.printInfo();
  w.run();
}

覆写父类的办法

class Person {
  String name;
  num age; 
  Person(this.name, this.age);
  void printInfo() {
    print("${this.name}---${this.age}");  
  }
  work(){
    print("${this.name}在工作...");
  }
}

class Web extends Person {
  Web(String name, num age) : super(name, age);
  run(){
    print('run');
  }
  
  //覆写父类的办法
  @override       //能够写也能够不写  倡议在覆写父类办法的时候加上 @override 
  void printInfo(){
     print("姓名:${this.name}---年龄:${this.age}"); 
  }
  
  @override
  work(){
    print("${this.name}的工作是写代码");
  }
}

main(){ 
  Web w = new Web('李四', 20);
  w.printInfo();
  w.work();
}

自类外面调用父类的办法

class Person {
  String name;
  num age; 
  Person(this.name, this.age);
  void printInfo() {
    print("${this.name}---${this.age}");  
  }
  work(){
    print("${this.name}在工作...");
  }
}

class Web extends Person {
  Web(String name, num age) : super(name, age);

  run(){
    print('run');
    super.work();  //自类调用父类的办法
  }
  
  //覆写父类的办法
  @override       //能够写也能够不写  倡议在覆写父类办法的时候加上 @override 
  void printInfo(){
     print("姓名:${this.name}---年龄:${this.age}"); 
  }
}

main(){ 
  Web w = new Web('李四', 20);
  w.printInfo();
  w.run();
}

抽象类

抽象类次要用于定义规范,子类能够继承抽象类,也能够实现抽象类接口。

1、抽象类通过abstract 关键字来定义

2、形象办法不能用abstract申明,没有办法体的办法咱们称为形象办法。

3、如果子类继承抽象类必须得实现外面的形象办法

4、如果把抽象类当做接口实现的话必须得实现抽象类外面定义的所有属性和办法。

5、抽象类不能被实例化,只有继承它的子类能够

extends抽象类 和 implements的区别:

1、如果要复用抽象类外面的办法,并且要用形象办法束缚自类的话咱们就用extends继承抽象类

2、如果只是把抽象类当做规范的话咱们就用implements实现抽象类

案例:定义一个Animal 类要求它的子类必须蕴含eat办法

abstract class Animal {
  eat();   //形象办法
  run();   //形象办法  
  printInfo(){
    print('我是一个抽象类外面的一般办法');
  }
}

class Dog extends Animal {
  @override
  eat() {
     print('小狗在吃骨头');
  }

  @override
  run() {
    print('小狗在跑');
  }  
}
class Cat extends Animal {
  @override
  eat() {
    print('小猫在吃老鼠');
  }

  @override
  run() {
    print('小猫在跑');
  }
}

main(){
  Dog d = new Dog();
  d.eat();
  d.printInfo();
  
  Cat c = new Cat();
  c.eat();
  c.printInfo();

  // Animal a=new Animal();   //抽象类没法间接被实例化
}

18 多态

容许将子类类型的指针赋值给父类类型的指针, 同一个函数调用会有不同的执行成果 。

子类的实例赋值给父类的援用。

多态就是父类定义一个办法不去实现,让继承他的子类去实现,每个子类有不同的体现。

abstract class Animal {
  eat();   // 形象办法 
}

class Dog extends Animal {
  @override
  eat() {
     print('小狗在吃骨头');
  }
  run(){
    print('run');
  }
}

class Cat extends Animal {
  @override
  eat() {   
    print('小猫在吃老鼠');
  }
  run(){
    print('run');
  }
}

main(){
  Dog d = new Dog();
  d.eat();
  d.run();

  Cat c = new Cat();
  c.eat();

  Animal d = new Dog();
  d.eat();

  Animal c = new Cat();
  c.eat();
}

19 接口

和Java一样,dart也有接口,然而和Java还是有区别的。

首先,dart的接口没有interface关键字定义接口,而是一般类或抽象类都能够作为接口被实现。

同样应用implements关键字进行实现。

然而dart的接口有点奇怪,如果实现的类是一般类,会将一般类和形象中的属性和办法全副须要覆写一遍。

而因为抽象类能够定义形象办法,一般类不能够,所以个别如果要实现像Java接口那样的形式,个别会应用抽象类。

倡议应用抽象类定义接口。

定义一个DB库 反对 mysql mssql mongodb

mysql mssql mongodb三个类外面都有同样的办法

abstract class Db {   // 当做接口   接口:就是约定 、标准
    String uri;       // 数据库的链接地址
    add(String data);
    save();
    delete();
}

class Mysql implements Db {
  
  @override
  String uri;

  Mysql(this.uri);

  @override
  add(data) {
    print('这是mysql的add办法'+data);
  }

  @override
  delete() {
    return null;
  }

  @override
  save() {
    return null;
  }

  remove() {
      
  }
}

class MsSql implements Db {
  @override
  String uri;
  @override
  add(String data) {
    print('这是mssql的add办法'+data);
  }

  @override
  delete() {
    return null;
  }

  @override
  save() {
    return null;
  }
}

main() {
  Mysql mysql = new Mysql('xxxxxx');
  mysql.add('1243214');
}

20 implements实现多个接口

abstract class A {
  String name;
  printA();
}

abstract class B {
  printB();
}

class C implements A, B {  
  @override
  String name; 
  
  @override
  printA() {
    print('printA');
  }
  
  @override
  printB() {
    return null;
  }
}

void main(){
  C c = new C();
  c.printA();
}

21 mixins

mixins的中文意思是混入,就是在类中混入其余性能。

能够应用mixins实现相似多继承的性能

因为mixins应用的条件,随着Dart版本始终在变,这里讲的是Dart2.x中应用mixins的条件:

1、作为mixins的类只能继承自Object,不能继承其余类

2、作为mixins的类不能有构造函数

3、一个类能够mixins多个mixins类

4、mixins绝不是继承,也不是接口,而是一种全新的个性

class A {
  String info = "this is A";
  void printA() {
    print("A");
  }
}

class B {
  void printB() {
    print("B");
  }
}

class C with A, B {

}

void main() {
  var c = new C();  
  c.printA();
  c.printB();
  print(c.info);
}

class Person {
  String name;
  num age;
  Person(this.name, this.age);
  printInfo() {
    print('${this.name}----${this.age}');
  }
  void run() {
    print("Person Run");
  }
}

class A {
  String info = "this is A";
  void printA() {
    print("A");
  }
  void run() {
    print("A Run");
  }
}

class B {  
  void printB() {
    print("B");
  }
  void run() {
    print("B Run");
  }
}

class C extends Person with B, A {
  C(String name, num age) : super(name, age);
  
}

void main() {  
  var c = new C('张三', 20);  
  c.printInfo();
  c.printB();
  print(c.info);
  c.run();
}

mixins的实例类型是什么?

很简略,mixins的类型就是其超类的子类型。

class A {
  String info = "this is A";
  void printA() {
    print("A");
  }
}

class B {
  void printB() {
    print("B");
  }
}

class C with A, B {
  
}

void main() {  
  var c = new C();  
  print(c is C);    //true
  print(c is A);    //true
  print(c is B);    //true
  
  var a = new A();
  print(a is Object);
}

22 泛型

泛型就是解决 类 接口 办法的复用性、以及对不特定数据类型的反对(类型校验)

泛型办法

// 只能返回string类型的数据
String getData(String value) {
  return value;
}
  
// 同时反对返回 string类型 和int类型  (代码冗余)
String getData1(String value) {
  return value;
}

int getData2(int value) {
  return value;
}

// 同时返回 string类型 和number类型       不指定类型能够解决这个问题
getData(value) {
  return value;
}

// 不指定类型放弃了类型查看。咱们当初想实现的是传入什么 返回什么。比方:传入number 类型必须返回number类型  传入 string类型必须返回string类型
getData<T>(T value) {
  return value;
}

void main() {
  print(getData(21));
  print(getData('xxx'));
  getData<String>('你好');
  print(getData<int>(12));
}

汇合List 泛型类的用法

案例:把上面类转换成泛型类,要求List外面能够减少int类型的数据,也能够减少String类型的数据。然而每次调用减少的类型要对立

class PrintClass<T> {
      List list = new List<T>();
      void add(T value){
          this.list.add(value);
      }
      void printInfo() {          
          for(var i = 0; i < this.list.length; i++) {
            print(this.list[i]);
          }
      }
 }

main() {  
  PrintClass p = new PrintClass<int>();
  p.add(12);
  p.add(23);
  p.printInfo();

  List list=new List<String>();
  // // list.add(12);  //谬误的写法
  list.add('你好');
  list.add('你好1');
  print(list);

  List list=new List<int>();
  // // list.add("你好");  //谬误写法
  list.add(12); 
  print(list);
}

泛型接口

实现数据缓存的性能:有文件缓存、和内存缓存。内存缓存和文件缓存依照接口束缚实现。

1、定义一个泛型接口 束缚实现它的子类必须有getByKey(key) 和 setByKey(key,value)

2、要求setByKey的时候的value的类型和实例化子类的时候指定的类型统一

abstract class Cache<T> {
  getByKey(String key);
  void setByKey(String key, T value);
}

class FlieCache<T> implements Cache<T> {
  @override
  getByKey(String key) {    
    return null;
  }

  @override
  void setByKey(String key, T value) {
   print("我是文件缓存 把key=${key}  value=${value}的数据写入到了文件中");
  }
}

class MemoryCache<T> implements Cache<T> {
  @override
  getByKey(String key) {   
    return null;
  }

  @override
  void setByKey(String key, T value) {
       print("我是内存缓存 把key=${key}  value=${value} -写入到了内存中");
  }
}
void main(){
  MemoryCache m = new MemoryCache<String>();
  m.setByKey('index', '首页数据');
  MemoryCache m = new MemoryCache<Map>();
  m.setByKey('index', {"name":"张三", "age":20});
}

23 库

后面介绍Dart基础知识的时候基本上都是在一个文件外面编写Dart代码的,但理论开发中不可能这么写,模块化很重要,所以这就须要应用到库的概念。

在Dart中,库的应用时通过import关键字引入的。

library指令能够创立一个库,每个Dart文件都是一个库,即便没有应用library指令来指定。

Dart中的库次要有三种

1、咱们自定义的库

import ‘lib/xxx.dart’;

2、零碎内置库

import ‘dart:math’;

import ‘dart:io’;

import ‘dart:convert’;

3、Pub包管理系统中的库

https://pub.dev/packages

https://pub.flutter-io.cn/pac…

https://pub.dartlang.org/flut…

1、须要在本人我的项目根目录新建一个pubspec.yaml

2、在pubspec.yaml文件 而后配置名称 、形容、依赖等信息

3、而后运行 pub get 获取包下载到本地

4、我的项目中引入库 import ‘package:http/http.dart’ as http; 看文档应用

导入本人本地库

import 'lib/Animal.dart';
main() {
  var a = new Animal('小黑狗', 20);
  print(a.getName());
}

导入零碎内置库

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

void main() async {
  var result = await getDataFromZhihuAPI();
  print(result);
}

// api接口: http://news-at.zhihu.com/api/3/stories/latest
getDataFromZhihuAPI() async {
  
  // 1、创立HttpClient对象
  var httpClient = new HttpClient();  
  
  // 2、创立Uri对象
  var uri = new Uri.http('news-at.zhihu.com','/api/3/stories/latest');
  
  // 3、发动申请,期待申请
  var request = await httpClient.getUrl(uri);
  
  // 4、敞开申请,期待响应
  var response = await request.close();
  
  // 5、解码响应的内容
  return await response.transform(utf8.decoder).join();
}

async和await

这两个关键字的应用只须要记住两点:

只有async办法能力应用await关键字调用办法

如果调用别的async办法必须应用await关键字

async是让办法变成异步。

await是期待异步办法执行实现。

void main() async {
  var result = await testAsync();
  print(result);

}

// 异步办法
testAsync() async{
  return 'Hello async';
}

导入Pub包管理系统中的库

pub包管理系统:

1、从上面网址找到要用的库

https://pub.dev/packages

https://pub.flutter-io.cn/pac…

https://pub.dartlang.org/flut…

2、创立一个pubspec.yaml文件,内容如下

name: xxx
description: A new flutter module project.
dependencies:
  http: ^0.12.0+2
  date_format: ^1.0.6

3、配置dependencies

4、运行pub get 获取近程库

5、看文档引入库应用

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

main() async {
  var url = "http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=1";
  
  // Await the http get response, then decode the json-formatted responce.
  var response = await http.get(url);
  if (response.statusCode == 200) {
    var jsonResponse = convert.jsonDecode(response.body);
    print(jsonResponse);
  } else {
    print("Request failed with status: ${response.statusCode}.");
  }
  print(formatDate(DateTime(1989, 2, 21), [yyyy, '*', mm, '*', dd]));
}

库的重命名 抵触解决

抵触解决

当引入两个库中有雷同名称标识符的时候,如果是java通常咱们通过写上残缺的包名门路来指定应用的具体标识符,甚至不必import都能够,然而Dart外面是必须import的。当抵触的时候,能够应用as关键字来指定库的前缀。如下例子所示:

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 lib2.

import 'lib/Person1.dart';
import 'lib/Person2.dart' as lib;
main(List<String> args) {
  Person p1 = new Person('张三', 20);
  p1.printInfo();

  lib.Person p2 = new lib.Person('李四', 20);
  p2.printInfo();
}

局部导入

如果只须要导入库的一部分,有两种模式:

模式一:只导入须要的局部,应用show关键字,如下例子所示:

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

模式二:暗藏不须要的局部,应用hide关键字,如下例子所示:

import 'package:lib2/lib2.dart' hide foo; 
//import 'lib/myMath.dart' show getAge;
import 'lib/myMath.dart' hide getName;

void main(){
//  getName();
  getAge();
}

提早加载

也称为懒加载,能够在须要的时候再进行加载。

懒加载的最大益处是能够缩小APP的启动工夫。

懒加载应用deferred as关键字来指定,如下例子所示:

当须要应用的时候,须要应用loadLibrary()办法来加载:

import 'package:deferred/hello.dart' deferred as hello;
greet() async {
  await hello.loadLibrary();
  hello.printGreeting();
}

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理