Flutter(二) Dart语法学习

2019-08-14  本文已影响0人  骑马纵天下

一. Dart入口方法

每一个flutter项目的lib目录里面都有一个main.dart。这个文件就是flutter的入口文件,其中的main方法是dart的入口方法。
runApp返回的是组件。MyApp是自定义的一个组件。在flutter里面万物皆组件。

# void是当前函数的返回值 可以省略
void main() {//程序执行的入口函数 有且仅有一个 必须的
   runApp(MyApp)
   print('Hello World!')//dart通过print方法打印数据
}
//如果runApp后面只有一行代码也可以这样写
void main() => runApp(MyApp());

二. Dart变量,常量和命名规则

  1. 变量
    dart是一个强大的脚本类语言,可以不预先定义变量类型,dart会通过类型推断 type inference(swift也是)自动判断当前变量的类型。dart中定义变量是通过var关键字或者通过类型来声明变量。
var str = '这是var变量';
String str1 = '这是类型声明的变量';
int number = 123;
注意: var 后不要写类型,写了类型不要写var 写了会报错 var a int = 5
  1. 常量

    常量通过final或者const修饰。

    差异之处:const修饰的常量在创建时就需要赋值(编译时的常量)赋值后不可改变。final不仅有const的编译时的常量特性,最重要的是它的运行时常量。并且final是惰性初始化,即在运行时第一次使用前才初始化。如果是不改量的量,请使用final或者cont修饰它,而不是使用var或者其他变量类型。

final name = ‘huang’;
final String rename = 'hai';
const bar = 100000; 
cont double atm = 1.01325 * bar 
  1. dart的命名规则
    • 变量等名称必须由数字、字母、下划线和美元符号($)组成。
    • 注意:标识符开头不能是数字。
    • 标识符不能使保留字或者关键字。
    • 变量的名称是区分大小写的如:age和Age是不同的变量。在实际的运用中,也建议不要用一个
    • 标识符(变量名称)一定要见名思意 :变量名称建议用名称,方法名称建议用动词

三. Dart基础数据类型

对应的①
/单引号 '' 或者 双引号 "" 来包裹字符组成字符串
  String str1 = '这是字符串';
  String str2 = "这是字符串";
  //使用 + 链接两个字符串
  String str3 = str1 + str2;
  print(str3);
  //多行字符串使用三重单引号 '''字符串'''
  //三重双引号 """字符串"""
  String str4 = """ 1111
  22222
  333333""";
  print(str4);
  //使用r前缀 可以使字符串里面的特殊字符作为普通字符串
//  \n 换行符 特殊字符
  String str5 = r'这是特殊字符\n现在不会换行';
  String str6 = '这是特殊字符\n现在会换行';
  print(str5);
  print(str6);
对应的②
var str4 = str + str1;
print('$str4 ${str4.length}');
// dart判断数据类型 is关键词用来判断数据类型
  if(str4 is String){
    // print()
  }
//print函数是控制套输出函数
  print('a 是 $a');
  print('你好dart');
  double c = 10;//double可以包含整型 整型 dart sdk 2.1 之前不能使用,会报错
  double d = 10.1;
  print('d = $d');

  num aa = -3; //num 是number类型的简写  abs()取绝对值
  print('asdasdas' + aa.abs().toString());
//ceil() 带小数就向前进一位取大于或者等于表达式的最小整数
  num h = 8.3;
  num i = h.ceil();
  print(i);
//floor()舍掉小数位 不管他多大
num j = 10.9;
num k = j.floor();
//round()四舍五入
bool value = true;
//  bool value2 = 'asda';//不合法
  bool value2 = false;
  if(value){
    print(value);
  }

四. Dart集合

//第一种定义List的方式
var list222 = ["asdsa","asdasd","asdsadff"];
list222.length; 获取长度
list222[0];获取第一个值
//第二种定义List的方式
var list111 = List();
list111.add('asdsdddda');//增加新值
list111.addAll(['hahah','asdasd']); 可以添加新的数组
//在定义List时 直接指定其类型
var List2223 = List<String>();//定义了一个只能放String类型的数组 调用其构造函数创建数组
//数组 里面的元素(值)可以重复  值的类型可以不同
List list1 = [1,2,3,4,5,6,7,8];
List list2 = [1,true,'qwe',1];
//常用属性
length  长度
reversed 数组翻转  对列表倒序排序
isEmpty 是否为空
isNoTEmpty 是否不为空
//常用方法
add 增加元素 增加一个
addAll 拼接数组
indexOf 查找数据 传入具体值 查到了返回元素所在位置索引 查找不到返回-1
remove 删除 传入具体值
removeAt 删除  传入索引值
fillRange 修改数据 传入开始索引和结束索引 然后传入要添加的值(1,10 ,'修改的值');
insert(index,value); 指定位置插值 (1 要添加的位置在索引为1的元素前添加 ,’要添加的值‘)
insertAll(index,List); 指定位置插入List 和上面的一样 只是传入的是数组
toList() 其他类型转换为List
join() List转换为字符串 传入变成字符串后的分割元素之间的符号
split() 字符串转换为List 传入通过哪些符号来分割字符串 变成List
forEach
map
where
any
every
//将key和Value相关联的对象
//key和Value都可以是任何对象
//定义方式 map字面量来定义
var person = {
"name" : "zhangsna",
"age" : 20,
"work" : ['haha','hehe']
};
 //可以直接添加或者修改值
person["name"]; //取值
var per = Map();
//  Map类型
Map dic = {'name': 'zhangsna', 'age': 20};
Map dic2 = new Map();//dart2.0版本后可以不用写new关键字
var dic3 = new Map();
 //从map中取值 如果map对象中没有对应的键 返回null
  print(tempMap2['sencond'].toString());
  // .length 取得map对象的长度
定义有两种形式 Set字面量 Set类型
  var s = Set();
  var set1 = {'value1','value2'};//Set字面量
  //Set类型
  //变量类型 决定
  Set set2 = {};
  //类型参数
  var set3 = <String>{};//指定元素为String类型的Set集合
  Set<String> set4 = {};
  //.add()添加至到集合
  set4.add('value1');
  print(set4);
//  .addAll 将元素为同类型的集合添加到现有集合
  set4.addAll(set1);
  print(set4);
// .length 得到集合的长度 里面多少个元素或者值
  print(set4.length.toString());
list.forEach((value){ 遍历数组 会把数组的每一个元素赋值给Value
     print("$value");
});

②. map方法和JS里map方法很像,遍历一个数组同时返回一个数组,遍历同时会给出每个元素value。

var newList = lsit.map((value){
   return value*2;
})

③. where方法遍历数组得到元素同时可以加判断语句

var newList = list.where((value){
    return value>5;
})

④. any方法遍历一个数组是否存在某个元素或者符合某些条件 返回 true false 只要集合里面有满足条件就返回true

var newList = list.any((value){
    return value>5;
})

⑤. every方法遍历一个数组是否存在某个元素 或者 符合某些条件 每一个都满足条件返回true否则返回false

var newList = list.every((value){
     return value>5;
})

五. 运算符

a = b++; 会先把b赋值给a 然后在加 ++ -- 标识自增 自减 1
a = ++b; 把b加上1 在赋值给a
//在赋值运算里面如果++ -- 写在前面 这个时候先运算 在赋值 如果++ --  写在后面 先赋值后运算
int aaaa = 13;
int bbbb = 5;
print(aaaa+bbbb);
print(aaaa-bbbb);
print(aaaa*bbbb);
print(aaaa/bbbb);
print(aaaa~/bbbb);
print(aaaa%bbbb);
print(aaaa == bbbb);
print(aaaa != bbbb);
print(aaaa > bbbb);
print(aaaa < bbbb);
print(aaaa <= bbbb);
print(aaaa >= bbbb);
b ??= 23; 表示如果b为空的话把23赋值给b
 var flag = true;
 var ccc = flag ? '正确' : '错误';
var aaa = 222;
var bbb = a ?? 333; //当a的值为空的时候把333赋值给bbb

六. 类型转换

String ahahah = '123';
var nnnnn = int.parse(ahahah);
var nnnnn = double.parse(ahahah);//转换为double
//如果传入的值为空 可以通过 try catch来判断
try{
    var nnnnn = int.parse(ahahah);
}catch (err){
    print('error');
//如果转换失败会跳到catch中
}
var aaasaa = 222;
aaasaa.isNaN //判断是否为空
print(aaaa.toString());

七. 循环语句 流程控制语句(控制流)

  for(int i = 0 ; i <= 100 ; i++ ){
    print(i);
  }
 // 打印0到50所有的偶数
  for(int i = 0 ; i <= 50 ; i++ ){
      if(i % 2 == 0){
        print(i);
      }
  }
//求1+2+3+4+5+++100的和
  var sum = 0;
  for(int i = 1 ; i <= 100 ; i++ ){
      
      sum += i;
  }
  //5050;
  while(表达式/循环条件){
    循环体
  }
  
  do{
    语句/循环体
  }while(表达式/循环条件)

八. Dart函数

dart中的函数 函数的定义 可选参数 默认参数 命名参数 箭头函数 匿名函数 闭包等 函数也叫方法 在类外面叫函数 在类内部叫方法 这个都无所谓 都可以叫函数 也可以叫方法

自定义方法的基本格式
返回类型 方法名称(形式参数1,形式参数2,......){
方法体 具体执行逻辑
return 返回值;
}
print();//内置方法/函数
String method (String name ,[int age,String sex]){
//形参 可选参数放到参数后面 用[]中括号包裹 用,逗号隔开
}
String method (String name ,[String sex = '男',int age]){
//形参 如果有默认参数 建议放到 不带默认参数的可选参数前面
}
String method (String name ,{String sex = '男',int age}){
//参数带名称的参数 需要用大括号包裹{}并且里面也可以设置默认参数
}
fn1(){
   print('fn1');
 }
 fn2(fn){
   fn();
 }
fn2(fn1);
//把方法函数fan1当做另一个方法fan2的形式参数传进去 然后执行
var fn = (){//没有方法名称
print('我是一个匿名方法');
}//直接通过变量fn调用方法
var printNumm = (){
//表示把一个函数赋值给了printNumm这个变量 调用方式和普通调用方法一样 传值方式和普通方法一样
}
list.forEach((valye) => print(value));
list.forEach((value) => {//里面也只能写一句代码
   print(value)//不用写分号
})
((int n){
//方法在创建好后会自动执行 因为方法后面有括号会直接调用这个方法 可以传入参数 和 接收参数  还可以指定类型 
   print('我是自执行方法');
})(12);
//就相当于在函数外面包裹了一个函数
var sum = 1;
fn(int n ){
    sum*=n;
    if(n == 1){
      return;
    }
    fn(n-1);//关键这句 在符合条件后在此执行当前方法 

}
fn(10);

闭包写法:函数嵌套函数,并return 里面的函数,这样就行成了闭包

fn(){ 
 var a = 123; /*不会污染全局 常驻内存 *//
 return (){
 a++;
 print(a);
 }
}
print(fn());

九. 类

dart所有的东西都是对象,所有的对象都继承自Object类。是一门使用类和单继承的面向对象语言,所有的对象都是类的实例,并且所有的类都是Object的子类。

一个类通常由属相和方法组成

1. 定义Person类
class Person{//类名首字母大写
  String name = '张三';
  int age = 23;
 //dart里面的构造函数可以写多个但是默认构造函数只能有一个
 Person(String name,int age){
  this.name = name;
  this.age = age;
  print('这是构造函数里面的内容,这个方法在实例化的时候触发')
 }
 //默认构造函数简写
 Person(this.name,this.age);
 //命名构造函数 可以有多个
 Person.now(){
    print('我是命名构造函数');
 }
  void getInfo(){
  print("${this.name}--$age");//this指当前类 类似self 通过this.需要用{}大括号包裹
}
}
2. 实例化类
var p1 = Person();//2.0.0后不用new关键字 写也可以 推荐不写
Person p2 = Person();//默认实例化类的时候调用的是默认构造函数
Person p3 = Person.now();//命名构造函数
var time = DateTime.now(); //实例化datetime 调用它的命名构造函数
//dart和其他面向对象语言不一样 dart中没有public private protected这些访问修饰符
但是我们可以使用 “_” 下划线 把一个属性或者方法定义成私有
String _name;//私有属性 私有属性可以通过共有的方法来访问 间接访问私有属性
_run(){//私有方法
    print('这是一个私有方法');//也可以通过公有方法来间接调用私有方法
}
alert(){
    this._run();//通过公有方法访问私有方法 私有的不能直接访问
}
3. 类中的getter和setter修饰符
get 名称{ //getter方法 也就方法获取数据
   return "返回值"
}
set 名称(形式参数){
//参数名称 = 形式参数;
}
4. 类中的初始化列表

dart中我们也可以在构造函数体运行之前初始化实例变量

int height;
int width
Rect():height = 2 , width= 3{//在实例化之前的操作

}
5. 静态成员

dart类中的静态成员:

  1. 使用static 关键字来实现类级别的变量和函数
  2. 静态方法不能访问非静态成员,非静态方法可以访问静态成员
  3. 静态方法成员变量不能在通过类的实例化对象访问 直接通过类来访问
static String name = "zhangsan";

static void show(){

}

void getInfo(){//非静态方法可以访问静态成员以及非静态成员

}
6. dart中的对象操作符
p1?.方法 如果p1对象不存在会自动返回 如果存在会访问方法
(p1 as Person).方法或者属性 //类型转换 转换为自己需要的类型
Person p1 = Person();
p1..name = "hhhh";
  ..age = 35;//连缀操作符 访问属性或者方法不用对象名可以直接访问
7. dart中的类的继承

通过super关键字来继承父类的属性和方法
重写父类方法是时@override关键字 建议加 可以不加
super.父类里面的方法 通过super调用父类的方法

  1. 子类使用extends类关键字来继承父类
  2. 子类会集成父类中可见的属性和方法 但是不会继承构造函数
  3. 子类能重写父类的方法getter和setter方法
8. dart中的抽象类 多态 和接口

dart抽象类主要用于定义标准,子类可以继承抽象类,可以实现抽象类的接口

  1. 抽象类通过abstract关键字来定义
  2. dart中的抽象方法不能用abstract声明,dart中没有方法体的方法我们称为抽象方法
  3. 如果子类继承抽象类必须得实现里面的抽象方法
  4. 如果把抽象类当做接口实现的话必须得实现抽象类里面定义的所有属性和方法
  5. 抽象类不能被实例化,只有继承它的子类可以

继承抽象类extends和implements关键字的区别

  1. 如果复用抽象类的方法,并且要用抽象方法约束自类的话我们就要用extends继承抽象类
  2. 如果只是把抽象类当做标准的话我们就用implements实现抽象类、

接口:就是约定规范

首先dart的接口没有interface关键字定义接口,而是普通类或者抽象类都可以作为接口被实现
同样适用implements关键字进行实现
但是dart的接口有点奇怪如果实现的类是普通类 会将普通类和抽象中的属性的方法全部需要重写一遍
而因为抽象类可以定义抽象方法,普通类不可以,所以一般如果要实现像Java接口那样的方式,一般会使用抽象类。
建议使用抽象类定义接口

abstract class Db{
    add();//只写方法不实现 继承它的子类需要实现它的方法属性
}
class Mysql implements Db{
    @override
    add(){

    }
}

dart中一个类实现多个接口 以及dart中的Mixins混入

abstract class a{
  add();//只写方法不实现 继承它的子类需要实现它的方法属性
}
abstract class b{
  remove();//只写方法不实现 继承它的子类需要实现它的方法属性
}
class implements a,b{
  //需要实现上面俩个抽象类的方法和属性 这叫一个类实现多个接口
}

Mixins的中文意思是混入 就是类中混入其他功能,在dart中可以使用mixins实现类似多继承的功能,因为mixins使用条件 随着dart的版本一直在变 这里讲的是dart2.x中使用mixins的条件

  1. 作为mixins的类只能继承自object 不能继承其他类
  2. 作为mixins的类不能有构造函数
  3. 一个类可以mixins多个mixins类

mixins不是继承也不是接口 而是一种全新的特性,mixins的实例类型就是其超类的子类型 c 混入a b 就是ab的子类型。通过with关键字实现class c with a,b{}c继承了a和b class c extends Person with a,b {}c继承于Person类同时混入了a b 如果继承的有同样的方法和属性 后面的会覆盖前面的

9. 泛型 泛型方法 泛型类 泛型接口

通俗理解:泛型就是解决 类 接口 方法的复用性,以及对不特定数据类型的支持(类型效验)

泛型一般在方法前面加T 啥都行 说明是泛型

①. 泛型方法
T getDate<T>(T value){
return value;
}

调用:

一般 getDate(123) 这个没有类型校验 传啥返回啥。
类型校验 getData<String>('123213'); 这个String会传给尖括号的T代表这个方法的返回值是String 接收值也是String

②. 泛型类
class Person<T>{
    List list = List<T>();
    void ad(T value){
        this.list.add(value);
    }
}

dart中的泛型接口:

  1. 定义一个泛型接口 约束实现它的子类必须有getByKey(Key) 和 setBuKey(key,value)
    2.要求setByKey的时候value的类型和实例化子类的时候指定的类型一致
abstract class Cache<T>{
  getByKey(steing key);
  void setByKey(string key ,T value);

}
class FlieCache<T> implements Cache<t>{
//继承泛型类 把当前类定义的泛型<T>传给父类的泛型<T>
 void setByKey(string key ,T value){

 }
}
③. async和await

记录:

函数如果有一行的话可以使用箭头函数 只要超过一行就不能使用箭头函数 (value) => print(value);
dart中所有的类都继承于Object类
$ 符 字符串插值运算符 $+变量名

//引入别的类
import 'package:async/async.dart';

Rune 符号文件 用来表达Unicode字符
Unicode为所有世界写作系统中使用的每个字母、数字和符号定义了唯一的数值。
Unicode采用UTF-32位编码 dart采用了UTF-64编码
为了在字符串中表达32位的Unicode值需要用到特殊语法
\uXXXX 以\u开始后面跟着4个十六进制数(XXXX) , x的取值范围是0到f

var tempStr = '\u0F00';
print(tempStr);

当到指定多于或者少于4个十六进制数字是,使用{}包裹该值

var smeil = '\u{1F600}';
print(smeil);

全局函数 可以在main方法中调用 全局作用域 方法参数被称为形式参数 形参 调用方法传入的参数被称为实际参数 实参

//自定义方法
void printInfo(){ 
  print('我是一个自定义方法');
  int getNum(){//方法里面还可以嵌套方法 一个返回值为int的方法 这个方法只能在 当前函数体内调用 局部作用域
    var myNum = 111;
    return myNum;
  }
}
上一篇下一篇

猜你喜欢

热点阅读