美文网首页
Flutter之Dart基础语法(二)

Flutter之Dart基础语法(二)

作者: Bfmall | 来源:发表于2023-08-15 09:48 被阅读0次

七.类 class

7.1. 类的定义
  1. 定义类用class关键字
  • 类通常有两部分组成:成员(member)和方法(method)。
  • dart没有public,private等关键字,使用下划线“_”来区分公有参数私有参数。
class 类名 {
  类型 成员名;
  返回值类型 方法名(参数列表) {
    方法实现
  }
}
  1. Dart2.0后,创建类对象可以省略 关键字new;
    类中访问类属性一般省略this,但是有命名冲突时,不可省略。
void main(List<String> args) {
  var p1 = Person();
  p1.eat();
}

class Person {
  String name = 'Tom';

  void eat() {
    String name = 'lucy';
    print(name);//lucy
    print(this.name);//Tom
  }
}
7.2. 构造方法

1.普通构造方法
Dart为类提供了默认的构造函数,当有了自己的构造函数,默认的构造方法将会失效,不能再使用。
这是因为Dart不支持函数重载

void main(List<String> args) {
  var p1 = Person('Tom');
}

class Person {
  var name;

  Person(String name1) {
    this.name = name1;
  }
  //等同于
  Person(this.name);
}
  1. 命名构造方法
class Person {
  var name;
  var age;
  var height;
  
  //命名构造方法
  Person.withArgments(String name, int age) {
    this.name = name;
    this.age = age;
  }
  //命名构造方法2
  Person.withArgments2();
    
  //命名构造方法,传入map
  Person.withMap(Map<String, Object>map) {
    this.name = map['name'];
    this.age = map['age'];
  }
  
  String toString() {
    return '$name, $age, $height';
  }
}

void main(List<String> args) {
  var p = Person.withMap({'name':'Frank','age':18});
  print(p);//Frank, 18, null

  Person p2 = Person.withArgments2();
  print(p2);//null, null, null
}
  1. 初始化列表 Initializer list
    final 初始化时必须赋值
//初始化列表
class Point {
  final num x;
  final num y;
  final num distant;

  Point(this.x,this.y) : distant = sqrt(x * x + y * y);
  //这种初始化变量的方法, 我们称之为初始化列表(Initializer list)
}

  var point = Point(3, 4);
  print(point.distant);
  1. 重定向构造方法
//重定向构造方法
class Person {
  String name;
  int age;

  Person(this.name,this.age);
  //重定向
  Person.withName(String nameStr) : this(nameStr, 10);
}
  1. 常量构造方法
    拥有常量构造方法的类中,所有的成员变量必须是final修饰的.
    为了可以通过常量构造方法,创建出相同的对象,不再使用 new关键字,而是使用const关键字
    如果是将结果赋值给const修饰的标识符时,const可以省略.
class Person {
  final String name;
  final int age;

  const Person(this.name,this.age);
}


  Person p = const Person('lucy', 18);
  Person p2 = const Person('lucy', 18);
  print(identical(p, p2));//true

  const Person p = Person('lucy', 18);
  const Person p2 = Person('lucy', 18);
  print(identical(p, p2));//true

  Person p3 = Person('lucy', 18);
  Person p4 = Person('lucy', 18);
  print(identical(p3, p4));//false

  1. 工厂构造方法(factory)
    Dart提供了factory关键字, 用于通过工厂去获取对象
    最大的特点就是可以手动返回一个对象,可以创建单例
class Person {
  final String name;

  static final Map<String, Person> cache = <String, Person>{};

  factory Person(String nameStr) {
    if (cache.containsKey(nameStr)) {
      final Person? p = cache[nameStr];
      return p!;
    } else {
      final p = Person.withName(nameStr);
      cache[nameStr] = p;
      return p;
    }
  }
  Person.withName(this.name);
}

  Person p3 = Person('lucy');
  Person p4 = Person('lucy');
  print(identical(p3, p4));//false
  1. 单例模式
//写法一
class Singleton {
  const Singleton._internal();
  factory Singleton() => const Singleton._internal();
}
Singleton single = Singleton();

//写法二
class Singleton {
  Singleton._privateInstance();
  static final Singleton instance = Singleton._privateInstance();
  factory Singleton(){
    return instance;
  }
}
//使用
Singleton single = Singleton();

//写法三
class Singleton {
  Singleton._internal();
  static final Singleton _instance = Singleton._internal();
  static Singleton getInstance() {
    return _instance;
  }
}
//使用
var instance = Singleton.getInstance();

//写法四
class Singleton {
    // 私有化构造方法
    Singleton._privateConstructor();
    static final Singleton _instance = Singleton._privateConstructor();
    //同下 : static Singleton get instance => _instance;
    static Singleton get instance { return _instance;}
}
//使用
var instance = Singleton.instance;

//写法五
class Singleton {
    Singleton._privateConstructor();
    static final Singleton instance = Singleton._privateConstructor();
}
//使用
void mian(){
    var instance = Singleton.instance;
    var instance2 = Singleton.instance;
    print(instance == instance2);
}
7.3 setter和getter
class Person {
  var name;

  set setName(String nameStr){
    name = nameStr;
  }

  String get getName{
    print('getName');
    return name;
  }
}

  Person p = Person();
  p.name = '123';
  print(p.getName);//getName  123
7.4 继承 extends

面向对象的其中一大特性就是继承,也是多态的使用前提。

Dart中的继承是单继承;
Dart中的继承使用extends关键字,子类中使用super来访问父类;
父类中的所有成员变量和方法都会被继承,,但是构造方法除外。
子类中可以调用父类的构造方法,对某些属性进行初始化:

子类的构造方法在执行前,将隐含调用父类的无参默认构造方法(没有参数且与类同名的构造方法)。
如果父类没有无参默认构造方法,则子类的构造方法必须在初始化列表中通过super显式调用父类的某个构造方法。

class Person {
  var name;

  Person(this.name);

  set setName(String nameStr){
    name = nameStr;
  }

  String get getName{
    print('getName');
    return name;
  }

  eat() {
  }

  run(){
    print('person run');
  }
}

class Student extends Person {
  int age;
  Student.withAge(String name, int age): this.age = age, super(name);

  @override
  run() {
    // TODO: implement run
    super.run();
    print('student run');
  }
}

  Student s =  Student.withAge('Tom', 18);
  s.name = '123';
  print(s.getName);//getName  123
  s.run();
  //person run
  // student run
7.5 抽象类 abstract

注意事项:

注意一:抽象类不能实例化.
注意二:抽象类中的抽象方法必须被子类实现, 抽象类中的已经被实现方法, 可以不被子类重写.

abstract class Animal {
  eat();
  run(){
  }
}

class Dog extends Animal {

  @override
  eat() {
    // TODO: implement eat
  }

}

class SmallDog extends Dog {
  @override
  run() {
    // TODO: implement run
  }
}
7.6 隐式接口 implements

Dart中的接口比较特殊, 没有一个专门的关键字来声明接口.

默认情况下,定义的每个类都相当于默认也声明了一个接口,可以由其他的类来实现(因为Dart不支持多继承)
必须实现抽象类中的所有方法;即在通过implements实现某个类时,类中所有的方法都必须被重新实现(无论这个类原来是否已经实现过该方法):

abstract class Eat {
  eat();
}
abstract class Run {
  run() {

  }
}

class Animal implements Eat,Run {

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

}
7.7 Mixin混入 mixin with

Mixin混入的方式

除了可以通过class定义类之外,也可以通过mixin关键字来定义一个类。
只是通过mixin定义的类用于被其他类混入使用,通过with关键字来进行混入。

mixin Eat {
  eat();
}
mixin Run {
  run(){
  }
}

class Animal with Eat,Run {

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

}

7.8 类的成员和方法
对象级别的的成员和方法

class Person {
  var name;
  int age;
  eat() {
  }
}

类级别的成员和方法

class Person {
  static var name;
  static final age = 18;
  static eat() {
  }
}

八.泛型

8.1. List和Map泛型
  //泛型写法 
  // List<Object>
  //_InternalLinkedHashMap<String, Object>
  var list = ['a','b','c',123];
  var dic = {'key1':'value1', 'key2':123};
  //限制类型
  var list2 = <String>['a','b','c'];
  var dic2 = <String, String>{'key1':'value1', 'key2':'value2'};
8.2. class泛型

Object类型

//object
class Person {
  Object name;
  Object age;
  Person(this.name, this.age);
}

  Person p = Person('yh',18);
  print(p.name.runtimeType);
  print(p.age.runtimeType);

T泛型

//T
class Person<T extends num> {
  T age;
  T height;
  Person(this.age, this.height);

  double sum(){
    double s = (this.age as int) * (this.height as double);
    return s;
  }
}

  Person p = Person(10,1.88);
  print(p.age.runtimeType);// int
  print(p.sum());// 18.799999999999997

九.空安全 “?”、“!”

为什么需要空安全?

目标:对于空安全而言,我们的目标是让您对代码中的 null 可见且可控,并且确保它不会传递至某些位置从而引发崩溃。

String? == String|Null

如果您能确定一条可空的表达式不为空, 您可以在其后添加 !让 Dart 处理为非空。

void main(List<String> arguments) {

  int? age = null;
  age = 10;
  double height = age! * 10.0;
  print(height);

  print('Hello world!');
}

与swift中的“?”、“!”基本相同。

十.库

在Dart中,库的使用可以使代码的重用性得到提高,并且可以更好的组合代码。

Dart中任何一个dart文件都是一个库,即使你没有用关键字library声明

10.1.库的导入

import语句用来导入一个库,后面跟一个字符串形式的Url来指定表示要引用的库,语法如下:

import '库所在的url';

常见的库URI有三种不同的形式

来自dart标准版,比如dart:io、dart:html、dart:math、dart:core(但是这个可以省略)

//dart:前缀表示Dart的标准库,如dart:io、dart:html、dart:math
import 'dart:io';

使用相对路径导入的库,通常指自己项目中定义的其他dart文件

//当然,你也可以用相对路径或绝对路径的dart文件来引用
import 'lib/student/student.dart';

Pub包管理工具管理的一些库,包括自己的配置以及一些第三方的库,通常使用前缀package

//Pub包管理系统中有很多功能强大、实用的库,可以使用前缀 package:
import 'package:flutter/material.dart';

库文件中内容的显示和隐藏:
如果希望只导入库中某些内容,或者刻意隐藏库里面某些内容,可以使用show和hide关键字

//show关键字:可以显示某个成员(屏蔽其他)
//hide关键字:可以隐藏某个成员(显示其他)
import 'lib/student/student.dart' show Student, Person;
import 'lib/student/student.dart' hide Person;
//库中内容和当前文件中的名字冲突

当各个库有命名冲突的时候,可以使用as关键字来使用命名空间

import 'lib/student/student.dart' as Stu;
Stu.Student s = new Stu.Student();
10.2. 库的定义

library关键字
通常在定义库时,我们可以使用library关键字给库起一个名字。

但目前我发现,库的名字并不影响导入,因为import语句用的是字符串URI

library math;

part关键字
在之前我们使用student.dart作为演练的时候,只是将该文件作为一个库。

在开发中,如果一个库文件太大,将所有内容保存到一个文件夹是不太合理的,我们有可能希望将这个库进行拆分,这个时候就可以使用part关键字了

不过官方已经不建议使用这种方式了:
mathUtils.dart文件

part of "utils.dart";

int sum(int num1, int num2) {
  return num1 + num2;
}

dateUtils.dart文件

part of "utils.dart";

String dateFormat(DateTime date) {
  return "2020-12-12";
}

utils.dart文件

part "mathUtils.dart";
part "dateUtils.dart";

test_libary.dart文件

import "lib/utils.dart";

main(List<String> args) {
  print(sum(10, 20));
  print(dateFormat(DateTime.now()));
}

export关键字
官方不推荐使用part关键字,那如果库非常大,如何进行管理呢?

将每一个dart文件作为库文件,使用export关键字在某个库文件中单独导入
mathUtils.dart文件

int sum(int num1, int num2) {
  return num1 + num2;
}

dateUtils.dart文件

String dateFormat(DateTime date) {
  return "2020-12-12";
}

utils.dart文件

library utils;

export "mathUtils.dart";
export "dateUtils.dart";

test_libary.dart文件

import "lib/utils.dart";

main(List<String> args) {
  print(sum(10, 20));
  print(dateFormat(DateTime.now()));
}

最后,也可以通过Pub管理自己的库自己的库,在项目开发中个人觉得不是非常有必要,所以暂时不讲解这种方式。

————————————————
版权声明:本文为CSDN博主「weixin_42580612」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42580612/article/details/124137706

相关文章

网友评论

      本文标题:Flutter之Dart基础语法(二)

      本文链接:https://www.haomeiwen.com/subject/totqmdtx.html