Flutter(一)Dart基础知识

57 阅读2分钟

本文中使用Android StudioFlutter 3.3.4来演示代码

Dart

Dart中的变量常量 varconstfinal

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;

image.png

字符串

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');
}

image.png

数组和字典

数组

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());
}

image.png

运算符

Dart中特殊的运算符:

  • ??=赋值运算:如果左边为nil就赋值,如果有值就直接返回

  • ??条件表达式:如果左边有值返回左边,没有就返回右边

 void test_operator_demo() {
  var a;
  a ??= 5;
  a ??= 10;
  print(a);

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

image.png

函数

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++);
}

image.png

这个例子就可以很清晰的看到闭包的作用

类变量、类方法

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));
  }

image.png

类的继承

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关键字混入BC,也就是多继承

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{

}

image.png

如果有同名的方法就会产生覆盖,如下

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{

}

image.png

作为混入类不能实现构造方法

如果在C中实现构造方法则会报错

image.png

混入类不要继承于别的类,原因也是防止别的类会实现构造方法

image.png

如果D中没有自己的成员变量和方法,则可以简写为class D = A with B,C;

image.png