本文中使用Android Studio
和Flutter 3.3.4
来演示代码
Dart
Dart
中的变量常量 var
、const
、final
Dart
中的变量常量:
- 使用
var
声明一个变量,可以赋值不同的类型 var
声明的变量如果没有初始化,那么它的值为nil
- 使用
final
声明的一个只能赋值一次的变量,它是最终变量
var a;
print(a);
a = 'hello';
print(a);
a = 100;
print(a + 1);
final b;
b = 10;
const c = 20;
字符串
Dart
中的字符串:
- 使用单引号和双引号创建
- 三个引号或双引号 创建多行字符串
- 双引号字符串相当于拼接,三引号字符串会记录换行等信息
- 字符串中想使用非转义字符,需要在字符串前加
r
- 字符串中想使用表达式或者变量的值需要使用
$
void test_string() {
String s1 = 'hello';
print(s1);
String s2 = "hello"
"world";
print(s2);
String s3 = '''hello
world''';
print(s3);
print(s1 + ' world');
print(s1[0]);
print(s1[1]);
print(s1 * 2);
String s4 = '123\n456';
print(s4);
String s5 = r'123\n456';
print(s5);
int a = 10;
int b = 20;
int c = a + b;
print('a + b = ${a + b}');
print('a + b = $c');
}
数组和字典
数组
Dart
中的列表可以存放不同的数据类型
void test_list_demo() {
var list = const ['Tom', 'Andy', 123];
print(list);
var list1 = ['Kevin','Tom', 'Jonh'];
list1.add('Lisa');
print(list1);
list1.insert(1, 'Tony');
print(list1);
var list2 = [1, 3, 7, 9, 2, 0 ,5];
list2.sort();
print(list2);
}
字典
void test_map_demo() {
var json = const {'one': 'Kevin'};
var json1 = {'one': 111, 'two': 222, 'three': 333};
print(json['one']);
json1['one'] = 1111;
print(json1);
var list = ['Kevin', 'Tony', 'John'];
print(list.asMap());
}
运算符
Dart
中特殊的运算符:
-
??=
赋值运算:如果左边为nil
就赋值,如果有值就直接返回 -
??
条件表达式:如果左边有值返回左边,没有就返回右边
void test_operator_demo() {
var a;
a ??= 5;
a ??= 10;
print(a);
var b;
print(b ?? a);
b = 10;
print(b ?? a);
}
函数
Dart
中的函数:
- 返回值和参数类型可以省略
- 当方法的执行语句只有一句的时候,可以使用
=>
箭头函数表达式 - 可选参数:传递参数的时候必须带上形参的名字
- 可选参数有两种方式
{}
和[]
,{}
调用时必须带形参的名字,[]
调用的时候不带形参的名字 - 方法也是一个对象,可以作为参数传递
- 匿名函数:没有方法名称的方法
- 闭包:定义在函数内部的函数就是闭包,闭包也是一个对象。闭包可以访问外部函数的局部对象
函数写法
void functionDemo() {
print(sum(10, 20));
}
int sum(int a, int b) {
return a + b;
}
// 简写(并不建议这么写,因为不是很直观)
sum(a, b) => a+b;
可选参数
void functionDemo() {
//print(sum1(10, c:30));
print(sum2(10, 0, 30));
}
// 调用的时候必须写形参的名字
int sum1(int a, {int? b, int? c}) {
b ??= 0;
c ??= 0;
return a - b + c;
}
// 调用的时候不带形参的名字,但是只能从左到右的顺序进行赋值
int sum2(int a, [int b = 0, int c = 0]) {
return a - b + c;
}
方法作为函数传递
void functionDemo() {
forEachDemo([1, 3, 5, 7], printElement);
}
forEachDemo(List list, void func(var element)) {
for(var e in list) func(e);
}
int b = 0;
printElement(var e) {
print('元素$b的值为:$e');
b++;
}
匿名函数
void functionDemo() {
int b = 0;
forEachDemo([2, 3, 5, 7], (var e) {
print('元素$b的值为:$e');
b++;
});
}
闭包
void closureDemo() {
funcA()();
funcA()();
funcA()();
var f1 = funcA();
f1();
f1();
f1();
f1();
var f2 = funcA();
f2();
f2();
}
funcA () {
int count = 0;
return () => print(count++);
}
这个例子就可以很清晰的看到闭包的作用
类变量、类方法
Dart
中类变量和类方法:
- 类变量和类方法必须用
static
修饰 - 类方法中只可以访问类变量,不能访问实例变量
- 实例方法中类变量和实例变量都可以访问
- 常量属性必须用
static
修饰
class StaticClass {
//静态属性
static int count = 1;
//实例属性
int currentCount = 0;
//常量属性必须用static修饰
static const String str = 'flutter';
//静态方法
static int sum(int a){
return a + count;
}
//实例方法
int sum2(int a){
return a + count + currentCount;
}
}
强制类型转换:
- 使用
as
- 使用
is
关键字提前判断
..
的链式调用是指每次返回的是对象本身,从下面的打印中可以看到
void staticClassDemo() {
var s = Object();
s = StaticClass();
// 强制类型转换
print((s as StaticClass).sum2(10));
print(s.sum2(20));
}
/提前类型判断
if(s is StaticClass){
print(s.sum2(20));
print(s..currentCount = 30..sum2(10));
print((s..currentCount = 30).sum2(10));
}
类的继承
Dart
中类的继承:
- 使用
extends
关键字表示继承 - 子类会继承构造方法以外的属性和方法
Dart
是单继承- 如果父类只有默认构造函数,子类默认构造函数会调用父类构造函数
- 若父类有其它构造函数,则子类需显示的调用父类的构造函数
class Person{
int? age;
int? height;
String? name;
// 有参数无函数名
Person(this.age);
// 有函数名五参数
Person.init();
// 有函数名有参数
Person.withName(this.name){
print('调用 Person.withName');
}
void say(){
print('age:$age, height:$height, name:$name');
}
}
class Student extends Person{
Student.withName(super.name) : super.withName();
Student.init() : super.init();
Student(super.age);
Student.iiiname(String? name) : super.withName(name) {
print('调用 Student(name)');
}
}
在Person
类中定义三个构造函数,则在继承Person
的类Student
中至少显示的调用一个父类中的构造函数
抽象类
类似于iOS
中的协议
abstract class AbstractClass {
String? name;
int sum(int a, int b);
}
abstract class AbstractClass1 {
int sum1(int a, int b);
}
abstract class AbstractClass2 {
int sum2(int a, int b);
}
class subClass implements AbstractClass, AbstractClass1, AbstractClass2{
@override
String? name;
@override
int sum(int a, int b) {
// TODO: implement sum
throw UnimplementedError();
}
@override
int sum1(int a, int b) {
// TODO: implement sum1
throw UnimplementedError();
}
@override
int sum2(int a, int b) {
// TODO: implement sum2
throw UnimplementedError();
}
}
多继承
类D
继承于A
并且使用with
关键字混入B
、C
,也就是多继承
void mixinDemo(){
D d = D();
d.a();
d.b();
d.c();
}
class A{
a() => print('A...');
}
class B{
b() => print('B...');
}
class C{
c() => print('C...');
}
class D extends A with B,C{
}
如果有同名的方法就会产生覆盖,如下
void mixinDemo(){
D d = D();
d.a();
}
class A{
a() => print('A...');
}
class B{
a() => print('B...');
}
class C{
a() => print('C...');
}
class D extends A with B,C{
}
作为混入类不能实现构造方法
如果在C
中实现构造方法则会报错
混入类不要继承于别的类,原因也是防止别的类会实现构造方法
如果D
中没有自己的成员变量和方法,则可以简写为class D = A with B,C;