1、开发准备
1.1 Dart 中文官网
https://dart.cn/
1.2 Win10下环境搭建
1.2.1 如果安装了Flutter-SDK,其实也可以直接使用里面的dart - sdk
1.2.2 如果之前没有安装 Flutter-SDK,请看如下步骤(在线方式)
安装 包管理器 chocolatey
- 点击右下级角的开始按钮,输入 cmd ,选择以管理员权限运行
Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
- 输入如下命令
@"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"
- 检测安装是否成功
choco -v
安装 dart-sdk
choco install dart-sdk
choco upgrade dart-sdk
1.2.3 离线方式安装,直接下载压缩包
1.3 开发工具选择
IntelliJ IDEA (以这个为例)
Android Studio
其它
1.4 插件的安装
在线方式
离线方式
-
查看跟IDEA对应的插件版本
去插件官网查找对应的版本
https://plugins.jetbrains.com/plugin/6351-dart/versions
1.5 项目创建
- 运行出现报错:Setting VM flags failed: Unrecognized flags: checked
-
把 Checked mode 勾取消即可
2、数据类型
2.1 变量与常量
变量
使用var声明变量,可赋予不同类型的值
未初始化时,默认值为null
使用fianl声明一个只能赋值一次的变量
常量
使用const声明常量
使用const声明的必须是编译期常量
-
const 与 final有着本质的区别
1)在定义const常量时,你必须直接赋一个字面量,而不能是一个变量或者公式;
2)在定义final常量时,如何赋值就无所谓了,但赋值后就不能再改了
2.2 内置类型
2.2.1 数值型-Number
Int 整型
double 浮点型
数值型操作
- 运算符: +、 -、 *、 /、 ~/、 %
- 常用属性:isNaN、 isEven、 isOdd等
-
常用方法:abs()、round()、floor()、ceil()、toInt()、toDouble()
2.2.2 字符串-String
字符串创建
使用单引号,双引号创建字符串
使用三个引号或双引号创建多行字符串
使用r创建原始raw字符串
2.2.3 布尔型-Boolean
使用bool表示布尔类型
布尔值只有true 和 false
2.2.4 列表-List
创建
- 创建List: var list = [1,2,3];
- 创建不可变的List:var list = const [1,2,3];
- 构造创建:var list = new List();
常用操作
List.length
List.add()
List.insert()
List.remove()
List.clear()
List.indexOf()
List.lastIndexOf()
List.sort()
List.sublist()
List.shuffle()
List.asMap()
List.forEach()
var list = ["hello","dart"];
print(list.length);
list.add("java");
print(list);
list.remove("java");
print(list);
print(list.indexOf("dart"));
print(list.indexOf("java"));
list.insert(0, "2020");
print(list);
print(list.sublist(1));
print(list.reversed);
list.sort();
print(list);
list.clear();
print(list);
2
[hello, dart, java]
[hello, dart]
1
-1
[2020, hello, dart]
[hello, dart]
(dart, hello, 2020)
[2020, dart, hello]
[]
2.2.5 键值对-Map
- 创建
- 创建Map
var language = {"first":"Dart", "second" : "java"};
- 创建不可变Map
var language = const {"first":"Dart", "second" : "java"};
- 构造创建
var language = new Map();
- 常用操作
1)Map.length
2)Map.isEmpty()、Map.isNotEmpty()
3)Map.Keys、 Map.values
4)Map.containsKey()、Map.containsValue()
5)Map.remove()
6)Map.forEach()
2.2.6 Runes、Symbols
3、运算符
3.1 算术运算符
加减乘除: +、-、*、/、~/、%
递增递减:++var、var++、--var、var--
3.2 关系运算符
运算符:==、!=、>、<、>=、<=
判断内容是否相同使用 ==
3.3 逻辑运算符
运算符:!、&&、||
针对布尔类型运算
3.4 赋值运算符
基础运算符:=、??=
复合运算符:+=、-=、*=、/=、%=、~/=
3.5 条件表达式
三目运算符:condition?expr1 : expr2
?? 运算符:expr1 ?? expr2
4、控制语句
4.1 if语句
if 语句
if...else if 语句
if...else if ...else 语句
4.2 for语句
for 循环
for ... in循环
4.3 while语句
while 循环
do ... while循环
4.4 break 和 continue语句
终止循环:break
跳出当前循环:continue
4.5 switch...case语句
比较类型:num、String、编译期常量
非空case必须有一个break
default 处理默认情况
continue跳转标签
5、方法
5.1 方法的定义
- 方法的定义与使用
返回类型 方法名 (参数1,参数2...){
方法体
return 返回值
}
方法的特性
方法也是对象,并且有具体类型Function
返回值类型、参数类型都可省略
箭头语法: => expr 是 { return expr; }缩写。只适用于一个表达式
方法都有返回值。如果没有指定,默认 return null 最后一句
5.2 可选参数
可选命名参数:{param1, param2, ...}
可选位置参数:{param1,param2, ...}
如果存在具体参数,可选参数声明,必须在参数后面
5.3 默认参数值
使用 = 在可选参数指定默认值
默认值只能是编译时常量
5.4 方法对象
方法可作为对象赋值给其它变量
方法可作为参数传递给其它方法
5.5 匿名方法
- 定义
(参数1. 参数2, ...) {
方法体
return 返回值
}
特性
可赋值给变量,通过变量进行调用
可在其它方法中直接调用或传递给其它方法
5.6 闭包
闭包是一个方法(对象)
闭包定义在其它方法内部
闭包能够访问外部方法内的局部变量,并持有其状态
void main(){
var func = a();
func();
func();
func();
}
a(){
int count = 0;
//闭包
// printCount(){
// print(count++);
// }
// return printCount;
// 更多是使用匿名方式的闭包
return (){
print(count++);
};
}
6、Dart 面向对象编程
6.1 类与对象
类与对象
使用关键字 class声明一个类
使用关键字new 创建一个对象,new 可省略
所有对象都继承于 Object类
void main(){
var person = new Person();
}
class Person{
int age;
String name;
}
-
属性与方法
1)属性默认会生成getter 和 setter方法
2)使用 final声明的属性只有 getter方法
3)属性和方法通过 . 访问
4)方法不能被重载
void main(){
var person = new Person();
person.name = "追梦小乐";
person.age = 20;
print(person.name);
print(person.age);
person.work();
print(person.address);
}
class Person{
int age;
String name;
final String address = "";
void work(){
print("姓名:$name 年龄:$age , is working.......");
}
}
-
类及成员的可见性
1)Dart 中的可见性以 library (库)为单位
2)默认情况下,每一个 Dart 文件就是一个库
3)使用 _ 表示库的私有性
4)使用 import 导入库
6.2 计算属性
顾名思义,计算属性的值是通过计算而来,本身不存储值
计算属性赋值,其实是通过计算转换到其它实例变量
void main(){
var rect = new Rectangle();
rect.width = 10;
rect.height = 20;
print(rect.area);
rect.area = 200;
print(rect.width);
}
class Rectangle {
num width,height;
//计算属性
// num get area {
// return width * height;
// }
//计算属性简写模式
num get area => width * height;
set area(value){
width = value / 10;
}
}
6.3 构造方法
-
默认构造方法
1)如果没有自定义构造方法,则会有个默认构造方法
void main(){
}
class Person{
int age;
String name;
final String gender = null;
Person(){
}
void work(){
print("working =============");
}
}
-
自定义构造方法
1)如果存在自定义构造方法,则默认构造方法无效
void main(){
Person person = new Person(20, "追梦小乐", "女");
}
class Person{
int age;
String name;
final String gender;
//语法糖形式
Person(this.age,this.name,this.gender);
// 一般形式,虽说跟语法糖形式作用一样,但是有个区别,就是final修饰的变量,在这里是不能被赋值的
// Person(int age,String name,String gender){
// this.age = age;
// this.name = name;
// this.gender = gender;
// }
void work(){
print("working ===============");
}
}
-
命名构造方法
1)构造方法不能重载
void main(){
Person person = new Person(20, "追梦小乐", "女");
new Person.withName("风行者", "男");
new Person.withAge(20, "男");
}
class Person{
int age;
String name;
final String gender;
//语法糖形式
Person(this.age,this.name,this.gender);
Person.withName(String name, this.gender){
this.name = name;
}
Person.withAge(int age, this.gender){
this.age = age;
}
void work(){
print("working ===============");
}
}
6.4 常量构造方法
如果类是不可变状态,可以把对象定义为编译时常量
使用 const 声明
void main(){
const person = const Person(20, "追梦小乐", "女");
person.work();
}
class Person{
final int age;
final String name;
final String gender;
//语法糖形式
const Person(this.age,this.name,this.gender);
void work(){
print("working ===============");
}
}
6.5 工厂构造方法
class Logger{
final String name;
static final Map _cache = {};
factory Logger(String name){
return Logger._internal("dart");
}
Logger._internal(this.name);
void log(String msg){
print(msg);
}
}
6.6 初始化列表
void main(){
var person = Person(20, "追梦小乐", "女");
person.work();
}
class Person{
int age;
String name;
final String gender;
//语法糖形式
Person(this.age,this.name,this.gender);
Person.withName(Map map) : gender = map["gender"]{
this.name = map["name"];
this.age = map["age"];
}
void work(){
print("working ===============");
}
}
6.7 静态成员
void main(){
var page = new Page();
page.scrollUp();
Page.scrollDown();
}
class Page{
static const int maxPage = 10;
static int currentPage = 1;
static void scrollDown(){
currentPage = 1;
print("scrollDown======");
}
void scrollUp(){
currentPage++;
print("scrollUp======");
}
}
6.8 对象操作符
- 条件成员访问 ?.
void main(){
Person person;
person ?.work();
}
class Person{
String name;
int age;
void work(){
print("Work......");
}
}
- 类型转换:as
void main(){
var person;
person = "";
person = new Person();
(person as Person).work();
}
class Person{
String name;
int age;
void work(){
print("Work......");
}
}
- 是否指定类型 :is , is!
void main(){
var person;
person = "";
if(person is Person){
person.work();
}
}
class Person{
String name;
int age;
void work(){
print("Work......");
}
}
- 级联操作: ..
void main(){
Person person = new Person();
person..name = "追梦小乐"
..age = 20
..work();
}
class Person{
String name;
int age;
void work(){
print("Work......");
}
}
6.9 对象call方法
void main(){
var person = new Person();
person.call("追梦小乐", 20);
}
class Person{
String name;
int age;
//返回值可以有,也可以为空,可以有参也可以无参
String call(String name,int age){
return "name is $name, age is $age";
}
}
你是怎样理解父类继承,接口实现和混入的?我们应该在什么场景下使用它们?
1.一般来讲,单继承,多实现,混入是多继承
A.继承是子类需要复用父类的方法实现
B.实现接口是复用接口的参数,返回值,和方法名,但不复用方法的实现,在Dart中实现抽象类 更像在java中实现用interface修饰的接口
C.混入是多继承,当被混入的类有多个同名方法时,调用子类的该方法时,会调用with声明的最后一个拥有该方法的类中的该方法,同时混入中的父类不能继承
在父类继承的场景中,父类子类之间的构造函数执行顺序是怎样的?如果父类有多个构造函数,子类也有多个构造函数,如何从代码层面确保父类子类之间构造函数的正确调用?
class Point {
num x, y;
Point() : this.make(0,0);
Point.left(x) : this.make(x,0);
Point.right(y) : this.make(0,y);
Point.make(this.x, this.y);
void printInfo() => print('($x,$y)');
}
class Vector extends Point{
num z = 0;
/*5个构造函数
Vector
Vector.left;
Vector.middle
Vector.right
Vector.make
*/
@override
void printInfo() => print('($x,$y,$z)'); //覆写了printInfo实现
}