Dart——入门

Dart

一.背景介绍

1.语言简介
(1)Dart是Google发布的一门开源编程语言。Dart是一种面向对象的语言,具有C语言风格的语法,可以选择将它编译成JavaScript。它支持各种编程辅助工具,如:接口,类,集合,泛型和可选类型。
(2)Dart可以广泛用于创建单页面应用程序。单页应用程序仅适用于网站和Web应用程序。单页应用程序可以在网站的不同屏幕之间进行导航,而无需在浏览器中加载不同的网页。一个典型的例子是GMail—当点击收件箱中的邮件时,浏览器会停留在同一个网页上,但JavaScript代码会隐藏收件箱并将邮件正文显示在屏幕上。
(3)谷歌发布了一个特殊的Chromium版本 - Dart VM 。使用Dartium可以在浏览器上进行测试之前,不必将代码编译为JavaScript。

下表是Dart和JavaScript的功能比较。

特征DartJavaScript
类型系统可选,动态弱,动态
单继承原型
接口多接口不支持
并发支持,隔离支持,使用HTML5网络worker

2.应用场景

  • Web开发
  • 跨平台移动应用开发(Flutter)
  • 脚本或服务端开发

3.Dart 环境安装
(1)Flutter
在编辑器(Android studio / Vs Code)中安装Flutter会直接安装Dart
(2)单独使用Dart
先安装Chocolatey ==》 使用管理员运行powershall ==》执行https://chocolatey.org/install中的安装命令
执行choco install dart-sdk 或者 下载压缩包
添加环境变量path

二.常量,变量,运算符
1.var 变量(和JS的var差不多一样)

var a;
print(a);// null 

var定义的变量如果未给初始值则打印出来为null

a = 10;
print(a);

给a再次赋值,a打印结果为10

a = "hello Dart";
print(a);

给a再次赋值,a打印结果为hello Dart

注意:如果先前使用var声明了a,如果再使用var声明a,则会报错 Context: Previous declaration of ‘a’(先前已经声明了a)

2.final (只能赋值一次)

final c = 30;
c = "final 只能赋值一次";
print(c);

final声明变量时只能为它赋值一次,如果再次赋值则会报错 Error: Can’t assign to the final variable ‘c’ (不能赋值给最终变量c)

3.const 常量
使用const声明的必须是编译期常量

注意:const声明的基本数据类型不能改变和Js中一样,但是Js中cosnt声明的变量如果为对象,则是可以改变对象中的属性值的,dart不能,const在dart中声明的常量不可映射,因此无法改变属性值

4.Dart中数据类型

内置数据类型:

  • 数值型-Number

  • 字符串-String

  • 布尔型-Boolean

  • 列表-List

  • 键值对-Map

  • (Runes Symbols 使用机会不多)

(1)数值型
num
  —— int (整型)
  —— double (浮点型)

int b = 20;
b = 20.5;
//报错 Error: A value of type 'double' can't be assigned to a variable of type 'int'.
double c = 33.33;
c = 30;
print(c);

注意:
   int 声明的变量不可以赋值为浮点型
   double 声明的变量可以赋值为整型,打印结果为浮点型
   Dart中也会出现精度缺失问题

(2)字符串
   使用单引号或者双引号创建字符串
   使用三个引号或双引号创建多行字符串
   使用r创建原始raw字符串

注意:Dart中字符串只能做+拼接作用,不能与数值型、布尔值等进行隐式转换

(3)dynamic
变量如果为动态,可以随意赋值任何类型、任何值的时候,此变量类型为dynamic

5.运算符

运算符: +、-、*、/、~/(取整)、%
常用属性:isNaN、isEven(是否偶数)、isOdd(是否奇数)
常用方法:abs()(取绝对值)、round()(把数四舍五入为最接近的整数)、floor()(对数进行下舍入)、ceil()(对数进行上舍入)、toInt()(转整型)、toDouble()(转浮点型)

三.字符串
1.运算符
+、*、==、[]
(1)

String name = '李大钊';
print('name:' + name) //name:李大钊 

(2)

String name = '李大钊';
print(name * 2) //李大钊李大钊 

(3)

String name = '李大钊';
print(name == '李大钊') //true

(4)

String name = '李大钊';
print(name[0]) //李

2.插值表达式
${expression}

int a = 1;
  int b = 2;
  print('a + b = ${a + b}');

3.字符串操作
常用属性:length、isEmpty、isNotEmpty
(1)str.length 可以获取到字符串的长度(这个字符串中单个字符的数量)
(2)str.isEmpty 是否为空
(3)str.isNotEmpty 是否不为空
(4)int.parse(str) 字符串转int(字符串中不能是小数)
(5)double.parse(str) 字符串转double
(6)num.toString() 转字符串
(7)num.toStringAsFixed(n) 保留精度 n为小数点后位数 (会四舍五入)
字符串切割
(8)substring  用于提取字符串中介于两个指定下标之间的字符
        str.substring(start,end);
        从str的第start个位置(包含这个位置)开始,截取到第end个位置(不包含这个位置)
        str.substring(index);
        从str的第index个位置开始,截取到字符串的末尾
(9)split 将字符串以指定的字符分割成一个数组
判断字符串是否包含或者以xxx开始 / 结束
(10)startsWith(‘xxx’) 判断字符串以xxx开始
    startsWith(‘xxx’,n) 判断字符串以xxx开始,从index = n 开始判断
(11)endsWith(‘xxx’) 判断字符串以xxx结束
endsWith(‘xxx’,n) 判断字符串以xxx开始,从index = n 开始判断
(12) contains('xxx) 判断字符串是否包含xxx
contains(‘xxx’,n) 判断字符串是否包含xxx,从index = n 开始判断
字符串替换
(13)replaceAll(‘a’,‘b’) 替换所有符合条件的,将所有a替换为b
(14)replaceFirst(‘a’,‘b’)只替换第一个符合条件的,将第一个a替换为b
(15)replaceRange(start,end,str)范围替换,将start–end的字符串替换为str,含start不含end
(16)indexOf(’xxx‘,index) 获取指定字符串在父级字符串中第一次出现的位置
               携带第二个参数则从index等于第二个参数处开始查找
(17)lastIndexOf(’xxx‘,index) 从后往前找 返回第一个符合条件的index
字符串转大小写
(18)toLowerCase 字符串转小写
(19)toUpperCase 字符串转大写
字符串去除空格
(20)trim 去除左右两边空格 trimRight 去除右边空格 trimLeft 去除左边空格
字符串补齐长度
(21)padLeft(length,str)从左边补齐
   padRight(length,str)从右边补齐

   length:补齐之后字符串的长度
   str:指定使用str字符串补齐。默认为''

  如果指定长度小于原字符串长度,则返回原字符串

四.List(数组)Js中为Array
1.创建数组

 var list1 = [1,2,3];
 var list2 = const [1,2,3]; //创建不可变的List
 var list3 = new List(3); //构造函数创建List [null, null, null]

在Js中使用构造函数创建数组,如果构造函数中传参,则参数为创建数组的长度,每个数组元素为empty。在Dart中,参数含义一样,只不过每个数组元素为null

2.数组操作
length 获取数组长度
add 从数组尾部添加元素
insert(index,el) 向数组index位置插入元素el
remove 删除数组index位置的元素 或者直接移除元素
clear 清空数组
indexOf 查找目标元素第一次出现的位置
lastIndexOf 查找目标元素最后一次出现的位置
sort 排序 可以传一个排序方法参数
sublist(start,end) 截取数组并返回新的数组
join 以指定的字符连接数组中所有的元素,形成一个新的字符串(数组本身不会发生变化)
followedBy 将自身和参数内list合成一个List

五.Map(键值对)类似于JSON,Object
1.创建数组

 var map1 = {'first': 'dart', 'second': 'java'};
 var map2 = const{'first': 'dart', 'second': 'java'};; //创建不可变的Map
 var map3 = new Map(); //构造函数创建Map {}

2.键值对操作
length 获取键值对长度
isEmpty 是否为空
isNotEmpty 是否不为空
keys 获取键值对的键
values 获取键值对的值
containsKey 返回是否包含某个key
containsValue 返回是否包含某个value
remove 移除键值
forEach 循环

六.条件表达式
1.三目运算符

condition ? express1 :express2 

2.??运算符

express1 ?? express2

3.if … else …
4.switch… case…

七.循环语句
1.for…
2.while …
3,do…while
…(与JS其他常用的差不多)

八.方法定义
1.返回类型 方法名 (参数){
方法体
return 返回值(可无返回值)
}
2.可选参数

printPerson1('张三',age:20);//可选参数为Map类型,给可选参数传参时要写参数名
printPerson2('李四',20);//可选参数为List类型,传参需要按参数位置来传参

//正常的参数需要在可选参数之前
printPerson1(String name,{int age, String gender}){
  print('name=$name,age=$age,gender=$gender');
}
printPerson2(String name,[int age, String gender]){
  print('name=$name,age=$age,gender=$gender');
}

3.默认参数

printPerson3('李四');

printPerson3(String name,{int age = 18, String gender = '男'}){
  print('name=$name,age=$age,gender=$gender');//name=李四,age=18,gender=男
}

九.面向对象
1.类与对象
使用关键字class声明一个对象
使用关键字new创建一个对象,new可省略
所有对象都继承于Object类
属性默认会生成getter和setter方法
使用final声明的属性只有getter方法
方法不能被重载
2.类及成员可见性
Dart中的可见性以library(库)为单位
3.计算属性
计算属性的值是通过计算而来,本身不存储值
计算属性赋值,其实是通过计算转换到其他实例变量

class Rectangle {
  num width,height;
  num get area => width * height;
      set area (value) {
        width = value / 20;
      }
}

4.构造方法
如果没有自定义构造方法,则会有默认的构造方法
如果存在自定义构造方法,则默认的构造方法无效
构造方法不能重载(不能命名一样)

//实例化构造函数
var persion = new Persion('Tom',20);

class Persion {
  String name;
  int age;
  // 构造方法,如果没有自定义构造方法,则会有默认的构造方法
  Persion(this.name,this.age);//构造函数的语法糖
}

(1)命名构造方法
使用命名构造方法,可以实现多个构造方法
使用类名.方法的形式实现

class Persion {
  String name;
  int age;
  // 构造方法,如果没有自定义构造方法,则会有默认的构造方法
  Persion(this.name,this.age);//构造函数的语法糖
  Persion.withName(String name, this.gender){
    this.name = name;
  }
}

(2)工厂构造方法
工厂构造方法类似于设计模式中的工厂模式
在构造方法前添加关键字factory实现一个工厂构造方法

class Logger {
  final String name;
  static final Map<String, Logger> _cache = <String, Logger>{};
  
  // 工厂构造方法
  factory Logger(String name) {
    if (_cache.containsKey(name)) {
      return _cache[name];
    } else {
      final logger = Logger._internal(name);
      _cache[name] = logger;
      return logger;
    }
  }
  Logger._internal(this.name); //构造函数不能有返回值

  void log(String msg) {
    print(msg);
  }
}

void main(List<String> args) {
  var map1 = new Logger('name');
  map1.log("2");
}

5.初始化列表
初始化列表会在构造方法执行之前执行
使用逗号分隔初始化表达式
初始化列表常用于设置final变量的值

6.静态成员
使用static关键字来实现类级别的变量和函数
静态成员不能访问非静态成员,非静态成员可以访问静态成员
类中的常量需要使用static const声明

void main(List<String> args) {
  var page = new Page();
  Page.scrollDown();
}
class Page {
  static const int maxPage = 10;// 类中的常量需要使用static const声明
  static int currentPage = 1;

  static void scrollDown () {
    currentPage = 1;
    print('scrollDown');
  }

  void scrollUp () {
     currentPage++;
     print('scrollUp');
  }
}

7.对象操作符

void main(List<String> args) {
  Persion persion;
  persion?.work;  // 相当于可选链
}

类型转换 as

(persion as Persion).work();

类型监测 is is!

if(persion is Persion){
    persion.work();
}

级链操作 …

var persion = new Persion();
persion..name = 'Tom'
       ..age = 20
       ..work();
new Persion()..name = 'Tom'
             ..age = 20
             ..work();     

8.对象call方法
如果类实现了call方法,则该类的对象可以作为方法使用

var persion = new Persion();
persion.name = 'Tom';
persion.age = 20;
//persion()  // 直接会执行call方法
print(persion('Test',30));

class Persion {
  String name;
  int age;

  // void work () {
  //   print('work');
  // }

  String call(String name,int age){
    print('name is $name.age is $age');
    return 'name is $name.age is $age';
  }
}

九.继承
使用extends继承一个类
子类会继承父类可见的属性和方法,不会继承构造方法
子类能够复写父类的方法、getter、setter
单继承,多态性

class Student extends Persion {
  void study(){
    print('Student study...');
  }
  
  // 可以复写父级方法
  @override // 修饰符说明这个是由父级来的
  bool get isAdult => age > 15;

  @override
  void run(){
    print('student run');
  }
}
class Persion {
  String name;
  int age;
  String birthday;

  bool get isAdult => age > 18;
  void run () {
    print('persion run...');
  }
}

(1)继承中的构造方法
子类的构造方法默认会调用父类的无名无参构造方法
如果父类没有无名无参构造方法,则需要显示调用父类构造方法
在构造方法参数后使用 : 显示调用父类构造方法
(2)构造方法执行顺序
父类的构造方法在子类构造方法体开始执行的位置调用
如果有初始化列表,初始化列表会在父类构造方法之前执行

class Student extends Persion {
  int age;
  final String gender;
  Student(String name,String gender) :gender = gender, super(name);  
}

class Persion {
  String name;
  // Persion(){ // 无名无参
  //   print('调用父级构造方法');
  // }
  Persion(this.name);
  Persion.withName(this.name);
}

(3)抽象类
抽象类使用 abstract 修饰,不能直接被实例化
抽象方法不用abstract修饰,无实现
抽象类可以没有抽象方法
有抽象方法的类一定得声明为抽象类

void main(List<String> args) {
  var person = new Student();
  person.run();
}

abstract class  Persion {
  void run();
}

class Student extends Persion {
  @override
  void run() {
    // TODO: implement run
    print('run');
  }
}

十.接口
类和接口是统一的,类就是接口
每个类都隐式的定义了一个包含所有实例成员的接口

class Persion {
  String name;
  int get age => 18;
  void run () {
    print('run...');
  }
}

// 使用implements关键字
class Student implements Persion{
  @override
  String name;

  @override
  // TODO: implement age
  int get age => throw UnimplementedError();

  @override
  void run() {
    // TODO: implement run
  }
}

如果是复用已有类的实现,使用继承
如果只是使用已有类的外在行为,使用接口

(1)Mixins
Mixins类似于多继承,是在多类继承中重用一个类代码的方式
作为Mixin的类不能有显示声明的构造方法
作为Mixin的类只能继承自Object
使用关键字with连接一个或多个Mixin

class A {
  void a(){
    print('a');
  }
}
class B {
  void b(){
    print('b');
  }
}
class Test {}
class C {
  void c(){
    print('c');
  }
}
class D extends A with B, C{
 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值