【Dart】=> [06] Dart初体验-类Class-构造函数-继承-mixin-异步编程-链式调用-泛型-异常

news2024/11/18 5:54:31

目录

    • 能够定义并使用Dart的类
    • 类的定义
    • 构造函数
    • 私有属性和方法
    • 继承
    • mixin
    • 异步编程
    • Future
    • Future链式调用
    • async - await
    • dynamic类型
    • 泛型
    • 异常

能够定义并使用Dart的类

Dart是一门面向对象的编程语言,所有的对象都是类的实例 通过类我们可以对数据和方法进行封装复用

学习内容:

  1. 类的定义
  2. 构造函数
  3. 私有属性和方法
  4. 继承
  5. mixin

类的定义

使用 class 关键字声明一个类,所有的类都是继承自 Object 类
类的组成:属性 和 方法
属性和方法都是通过 . 访问的
例子:定义一个Person类,属性是名字和年龄,方法是吃饭

在这里插入图片描述
在这里插入图片描述
整体代码

void main() {
  // 创建Person对象
  // Person person = Person();
  // // 给属性赋值
  // person.name = '张三';
  // person.age = 18;

  // 使用自定义类名构造函数创建对象
  // Person person = Person('李四', 19);

  // 使用命名构造函数创建对象
  // Person person = Person.withName('王五');

  // 使用工厂构造函数创建对象
  // Person person = Person.withInfo('赵六', 21);
  Person person = Person.withInfo('赵六', -21);

  print('我叫 ${person.name} 今年 ${person.age}');

  Person person1 = Person.withAge(20);
  print(person1.age);

  // 调用方法
  person.eat();
}

// 例子:定义Person类,属性:名字和年龄,方法:吃饭
class Person {
  // 默认的构造函数(无参数,默认隐藏)
  // Person() {
  //   print('我是默认的构造函数');
  // }

  // 自定义类名构造函数:可以有参数
  // 注意点:与类同名的构造函数只能有一个,如果自定义了类名构造函数,那么默认的构造函数就失效
  // Person(String name, int age) {
  //   this.name = name;
  //   this.age = age;
  // }

  // 简写:自定义类名构造函数时,如果函数的参数和类的属性同名
  Person(this.name, this.age);

  // 定义命名构造函数
  // Person.withName(String name) {
  //   this.name = name;
  // }
  // 简写
  Person.withName(this.name);
  Person.withAge(this.age);

  // 定义工厂构造函数
  // factory Person.withInfo(String name, int age) {
  //   // 需要手动的创建对象并返回
  //   return Person(name, age);
  // }

  // 例子:如果age < 0,那么person对象的年龄默认设置为0
  factory Person.withInfo(String name, int age) {
    // 需要手动的创建对象并返回
    return age < 0 ? Person(name, 0) : Person(name, age);
  }

  // 属性
  String? name;
  int? age;

  // 方法
  void eat() {
    print('我是干饭人');
  }
}

构造函数

创建对象时调用的函数,常用的构造函数有:

  1. 类名构造函数
  2. 命名构造函数
  3. 工厂构造函数

类名构造函数,与类同名的构造函数

  1. 默认构造函数(无参数,默认隐藏)

在这里插入图片描述

  1. 自定义类名构造函数(可以有参数)
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

注意点:类名构造函数,只能有一个,如果自定义了类名构造函数,那么默认的类名构造函数就无效了

命名构造函数,可以为类提供多个不同的构造函数
定义方式:类名.函数名() {}

 // 简写:自定义类名构造函数时,如果函数的参数和类的属性同名
  Person(this.name, this.age);

  // 定义命名构造函数
  // Person.withName(String name) {
  //   this.name = name;
  // }
  // 简写
  Person.withName(this.name);
  Person.withAge(this.age);

工厂构造函数,不会直接创建对象,而是在构造函数内部通过代码来决定要创建的对象
定义方式: 使用 factory 关键字声明工厂构造函数

  // 定义工厂构造函数
  // factory Person.withInfo(String name, int age) {
  //   // 需要手动的创建对象并返回
  //   return Person(name, age);
  // }


例子:如果创建Person对象时,age < 0,则该Person对象的年龄默认设置为0

  // 例子:如果age < 0,那么person对象的年龄默认设置为0
  factory Person.withInfo(String name, int age) {
    // 需要手动的创建对象并返回
    return age < 0 ? Person(name, 0) : Person(name, age);
  }

使用场景:当需要根据条件来决定要返回的对象时,比如:单例

私有属性和方法

  1. 私有属性和方法:
    在类中定义,不对外暴露,不能被其他Dart文件访问的属性和方法
  2. 如何定义私有属性和方法:
    使用 _ 定义属性和方法
// 导入Dart文件、库
import '28_类_私有属性和方法.dart';

void main() {
  // 创建Dog对象
  Dog dog = Dog();

  dog.name = '旺财';
  print(dog.name);

  // 私有属性调用失败
  // dog._age;

  dog.eat();
  // 私有方法调用失败
  // dog._run();
}

继承

通过继承可以让子类拥有父类的一些属性和方法。如何实现继承:

  • 如何实现继承:
    • 子类使用 extends 关键字继承父类
  • 继承的特点:
    • Dart的继承是单继承,一个子类只能有一个父类
    • 子类只会继承父类里面可见的属性和方法,不会继承私有属性和方法
    • 子类只会继承父类默认的构造函数,不会继承其他构造函数
    • 子类可以重写父类的方法,也可以使用 super 调用父类方法
void main() {
  // 创建猫
  // Cat cat = Cat();
  // cat.name = 'Tom';

  Cat cat = Cat('Tom');
  print(cat.name);

  cat.eat();
  cat.walk();

  // 创建鱼
  // Fish fish = Fish();
  // fish.name = '鲨鱼';

  Fish fish = Fish('鲨鱼');
  print(fish.name);

  fish.eat();
  fish.swim();
}

// 猫,吃饭和走路
class Cat extends Animal {
  Cat(String name) : super(name);

  // String? name;

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

  // 重写父类的方法
  
  void eat() {
    // 执行子类自己的逻辑
    print('执行子类自己的逻辑');

    // 使用super去调用父类的方法
    // super.eat();
  }

  void walk() {
    print('walk');
  }
}

// 鱼,吃饭和游泳
class Fish extends Animal {
  // 定义子类自己的构造函数,并且使用super调用父类的构造函数传递数据
  Fish(String name) : super(name);

  // String? name;

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

  void swim() {
    print('swim');
  }
}

// 定义一个父类,父类里面有其他类都有的属性和方法
// 使用继承,让子类继承父类,从而子类就自动拥有了父类的属性和方法
class Animal {
  // 自定义类名构造函数
  // 如果父类自定义构造函数,那么子类继承不到,所以子类需要自己定义构造函数
  Animal(this.name);

  String? name;

  void eat() {
    print('eat');
  }
}

// class Animal1 {
//   String? age;

//   void sleep() {
//     print('eat');
//   }
// }

mixin

mixin 可以理解为扩展类,可以为类扩展功能,而不需要使用继承,类似Vue里面的混入。

如何定义并使用 mixin

  • 定义:mixin 关键字
  • 使用:with 关键字

mixin 的特点:

  • 可以扩展属性和方法
  • 不能被实例化,不能被继承
void main() {
  Person person = Person();

  // name是继承的
  person.name = '张三';
  print(person.name);

  // height是通过mixin扩展的
  person.height = 180.0;
  print(person.height);

  // eat()是继承的
  person.eat();

  // walk()是通过mixin扩展的
  person.walk();
  person.study();

  // mixin不能被实例化,不能被继承
  // WalkMixin();
}

// mixin可以使用多个
mixin StudyMixin {
  void study() {
    print('study');
  }
}

// 定义mixin
mixin WalkMixin {
  double? height;

  void walk() {
    print('walk');
  }
}

// 人,吃饭和走路
class Person extends Animal with WalkMixin, StudyMixin {
  // String? name;

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

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

// 猫,吃饭和走路
class Cat extends Animal with WalkMixin {
  // void walk() {
  //   print('walk');
  // }
}

// 鱼,吃饭和游泳
class Fish extends Animal {
  void swim() {
    print('swim');
  }
}

// 定义基类:动物
class Animal {
  String? name;

  void eat() {
    print('eat');
  }

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

异步编程

能够使用Dart异步编程解决耗时操作阻塞程序的问题

在Web端和APP中,有很多耗时操作都需要 异步执行
Web端的异步解决方案是 Promise,再配合 async – await 更能以同步的方式编写异步代码
Dart也同样提供了异步解决方案 Future ,也可以配合 async – await 使用

学习内容:
1.Future
2.async - await

Future

  • Future是一个表示延迟计算的对象。代表一些计算将异步进行
  • Future会在耗时操作执行完毕前直接返回,而不会等待耗时操作执行结束
  • 例子:模拟耗时操作阻塞程序,并使用Future解决程序阻塞问题
// 模拟耗时操作阻塞程序的问题,并使用Future解决阻塞问题
  print('开始喽');

  Future(() {
    // 耗时任务执行的地方
    sleep(Duration(seconds: 5));

    // 故意编写的异常代码(测试)
    // dynamic str = 'hehe';
    // str.haha();

    // 返回异步任务执行的结果
    return '假装这是异步任务执行的结果';
  }).then((value) {
    // 监听异步任务执行结束
    print(value);
  }).catchError((e) {
    // 捕获异常信息
    print(e);
  });

Future链式调用

例子:用户先登录并获取用户信息,再保存用户信息

// Future链式调用
  // 用户先登录拿到用户信息,然后再保存用户信息
  Future login(String name, String password) {
    return Future(() {
      sleep(Duration(seconds: 2));
      print('登录操作');
      return 'userInfo';
    });
  }

  Future saveUserInfo(String userInfo) {
    return Future(() {
      sleep(Duration(seconds: 2));
      print('保存用户信息');
      return 'OK';
    });
  }

  // Future链式调用
  login('张三', '123456').then((value) {
    saveUserInfo(value);
  });

  print('假装这是个不能被阻塞的代码');

async - await

  1. Future 配合 async – await 以同步的方式编写异步代码
  2. 例子:用户先登录并获取用户信息,再保存用户信息
 // Future链式调用
  // 用户先登录拿到用户信息,然后再保存用户信息
  Future login(String name, String password) {
    return Future(() {
      sleep(Duration(seconds: 2));
      print('登录操作');
      return 'userInfo';
    });
  }

  Future saveUserInfo(String userInfo) {
    return Future(() {
      sleep(Duration(seconds: 2));
      print('保存用户信息');
      return 'OK';
    });
  }

  // Future链式调用
  // login('张三', '123456').then((value) {
  //   saveUserInfo(value);
  // });

  // async await
  void doLogin() async {
    String userInfo = await login('李四', '123456');
    await saveUserInfo(userInfo);
  }

  doLogin();

  print('假装这是个不能被阻塞的代码');

dynamic类型

能够知道dynamic类型的特点

在Dart中,虽然有类型推断和类型检查
但是,还可以使用 dynamic 关键字关闭变量的类型检查

特点:
编码灵活,可以保存任意类型的数据
容易产生 NoSuchMethodError 的异常

void main() {
  int a = 15;
  // a = 'itcast';
  a = 20;

  // dynamic会关闭编译器的类型检查
  dynamic b = 100;
  b = 'itheima';
  print(b);

  // b.haha();
  // b.hehe;
}

泛型

能够知道泛型的作用

泛型是指类型的不确定性,数据具体的类型可以在使用时确定

  1. 使用泛型可以限定类型
  // 泛型限定数据的类型:List Map
  // 保存视频分类名称时,不应该出现100 true这样类型的数据
  // List categories = ['居家', '美食', 100, true];

  List<String> categories = ['居家', '美食'];
使用泛型可以明确约束列表元素的类型

使用泛型可以明确约束字典的key和value的类型
 Map<String, String> category = {
    'id': '1',
    'name': '居家',
  };
  1. 使用泛型可以减少重复代码
  // 封装方法:接收什么类型的数据,就返回什么类型
  T demo<T>(T parm) {
    return parm;
  }

异常

能够知道如何捕获并处理异常

  1. 如何捕获异常:
    使用关键字 try catch 捕获并处理异常
    finally:无论是否有异常都会执行到的语句块
  // 捕获异常:try catch
  // try {
  //   dynamic name = 'zzm';
  //   name.haha();
  // } catch (e) {
  //   print(e);
  // } finally {
  //   // 无论是否有异常都会执行这个代码块
  //   print('finally');
  // }
  1. 如何手动抛出异常:使用关键字 throw 手动抛出异常

  // 手动抛出异常:判断字符串是否相等,如果不相等手动抛出异常
  try {
    String str = 'zzm';
    if (str == 'zxc') {
      print('ok');
    } else {
      // 手动抛出异常
      throw '字符串不相等';
    }
  } catch (e) {
    print(e);
  }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1386291.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JVM基础(8)——CMS垃圾回收器

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 学习必须往深处挖&…

企业销售人员都在用的客户管理CRM软件有哪些?

“目前我公司需要用到软件的人数不超过10个&#xff0c;主要销售模式是电话、拜访为主&#xff0c;产品是称重设备&#xff0c;客户是工厂。” 上面的需求整理了一下&#xff1a; 团队规模&#xff1a;小规模&#xff0c;不超过10人——尽可能降低使用成本使用人员&#xff1a;…

C++结合OpenCV:图像的加法运算

一、图像运算 针对图像的加法运算、位运算都是比较基础的运算。但是&#xff0c;很多复杂的图像处理功能正是借助这些基础的运算来完成的。所以&#xff0c;牢固掌握基础操作&#xff0c;对于更好地实现图像处理是非常有帮助的。本章简单介绍了加法运算、位运算&#xff0c;并…

CG Magic分享3dmax渲染太亮问题如何解决?

3D Max软件渲染时&#xff0c;渲染问题较多也是正常的&#xff0c;对于行业小白来说&#xff0c;渲染问题多也是能理解的&#xff0c;因为&#xff0c;小编经常在问答中&#xff0c;看到一些网友提问&#xff0c;3dmax渲染太亮怎么办&#xff1f; 3dmax渲染太亮了怎么回事&…

如何定位和优化程序CPU、内存等性能之巅

摘要 性能优化指在不影响系统运行正确性的前提下&#xff0c;使之运行得更快&#xff0c;完成特定功能所需的时间更短&#xff0c;或拥有更强大的服务能力。本文将介绍性能优化的基本概念以及如何定位和优化程序中的CPU、内存和IO瓶颈。 引言 随着计算机系统的日益复杂和应用…

有哪些windows录屏软件?

有哪些windows录屏软件&#xff1f;随着技术的发展&#xff0c;使用Windows录屏软件已成为一种非常方便的方式&#xff0c;可以帮助人们记录和分享他们在计算机上的操作过程。例如&#xff0c;您可以使用录屏软件记录您在编辑文档或演示新产品时的屏幕操作&#xff0c;并将其用…

BIOS知识枝桠——RAID 磁盘阵列

文章目录 前言一、RAID介绍二、RAID等级分类1.RAID02.RAID13.RAID24.RAID3和RAID45.RAID5和RAID66.RAID77.RAID10 BIOS下组建RAID 前言 假设存在多块磁盘&#xff0c;如果不组建阵列&#xff0c;磁盘与磁盘之间是没有任何关系的。磁盘A和B&#xff0c;放在A中的文件与B磁盘没有…

自学Python笔记总结(更新中……)

自学Python笔记总结 网址数据类型类型查看类型&#xff0c;使用type内置类标识符 输出输入语句format函数的语法及用法数据类型的转换运算符算数运算符赋值运算符的特殊场景拆包 比较运算符逻辑运算符 与 短路位运算符运算符优先级 程序流程控制分支语句pass 占位 循环语句 whi…

可应用于电脑主板等产品上的精密基准电路WL431 输出电压可设定 响应速度快

WL431为三端可调节精密基准源。通过两个外接电阻&#xff0c;输出电压可在Vref约2.5 V )到36V连续调节。该电路输出阻抗小(0.2Q)。 开启特性好&#xff0c;在许多应用场合&#xff0c;它能较好地替换齐纳极管。 主要特点&#xff1a;● 温度系数 50pmC ● 在…

荣耀开发者大会2023 · 一张图读懂智慧人机交互分论坛

荣耀智慧人机交互&#xff0c;以用户意图理解为主的智慧交互&#xff0c;平台级AI使能主动理解用户意图&#xff0c;服务找人能力全面升级&#xff01; 荣耀智慧门能精准理解用户交互意图&#xff0c;覆盖100头部应用&#xff0c;支持文本、图片等元素类型随心拖拽&#xff0c…

自媒体必备的8个素材网站,免费可商用。

自媒体必备的8个素材网站&#xff0c;视频、音效、音频、图片等素材非常齐全&#xff0c;免费下载&#xff0c;无需担心侵权&#xff0c;赶紧收藏起来吧~ 视频素材 1、菜鸟图库 https://www.sucai999.com/video.html?vNTYwNDUx 菜鸟图库可以找到设计、办公、图片、视频、音频…

基于树莓派5(Raspberry Pi 5)的高性能工业平板电脑升级版!

​ 上海晶珩继推出首个搭载 Raspberry Pi 5 的平板电脑ED-HMI3010系列后&#xff0c;又推出了具备高性能和多功能特性的 Raspberry Pi 5 的平板电脑ED-HMI3020系列。ED-HMI3020支持选择7英寸和10.1英寸两种尺寸的触摸屏&#xff0c;可选配 M.2 NVMe SSD 存储扩展&#xff0c;提…

new mars3d.graphic.PolygonEntity({计算平面几何中心点及贴地效果展示

1.Mars3d提供了几何图形相关点位的计算方法polyutil&#xff1a; PolyUtil - V3.7.0 - Mars3D API文档 2.通过api可以算出相关经纬度坐标&#xff0c;实现相关中心点的展示 &#xff1a; 功能示例(Vue版) | Mars3D三维可视化平台 | 火星科技 3.相关实现代码&#xff1a; fu…

HCIP的静态路由复习

VRP设置用户名密码登录 [R1]aaa [R1-aaa]local-user TMG password cipher huawei #创建一个名TMG的用户&#xff0c;密码huawei Info: Add a new user.[R1-aaa]local-user TMG privilege level 15 #设置权限 [R1-aaa]local-user TMG service-type terminal …

个性化定制的知识付费小程序,为用户提供个性化的知识服务

明理信息科技知识付费saas租户平台 随着知识经济的兴起&#xff0c;越来越多的人开始重视知识付费&#xff0c;并希望通过打造自己的知识付费平台来实现自己的知识变现。本文将介绍如何打造自己的知识付费平台&#xff0c;并从定位、内容制作、渠道推广、运营维护四个方面进行…

恒温器探针样品座

恒温器探针样品座是一种用采用可移动探针完成恒温器电缆和被测样品的电学连接&#xff0c;避免了每次样品电引线的焊接&#xff0c;探针可移动&#xff0c;5mm--20mm大小的样品均可适用&#xff0c;探针可以安装6个&#xff0c;标准配置探针数量为4个。 恒温器探针样品座由T型…

安装tesseract

Tesseract OCR是一款由HP实验室开发由Google维护的开源OCR引擎&#xff0c;在字符识别领域发挥着举足轻重的作用。除了使用软件自带的中英文识别库&#xff0c;我们可以使用Tesseract OCR训练属于自己的字库。 下载地址&#xff1a;https://digi.bib.uni-mannheim.de/tesseract…

自动化革命:大象机器人的Mercury A1机械臂

引言 大象机器人的Mercury系列&#xff0c;是面向工业自动化和智能制造的新型机械臂产品线。这些机械臂不仅在设计上创新&#xff0c;还在材料选择上使用了碳纤维、铝合金和工程塑料等轻质强韧材料&#xff0c;搭载高精度谐波减速器。Mercury系列的推出&#xff0c;反映了大象机…

【CSS】解决height = line-height 文字不垂直居中(偏上、偏下)的问题

解决办法1&#xff1a; 查看 font-family 属性&#xff0c;确认是否是因为字体而导致的不垂直居中问题。 其他小知识&#xff1a; 基线就是小写x字母的下边缘(线) 就是我们常说的 基线。line-height 属性设置的行高也就是定义的两行文字基线之间的距离! 参考文章&#xff1a;…

为什么单片机上的程序不怎么使用malloc,而PC上经常使用?

为什么单片机上的程序不怎么使用malloc&#xff0c;而PC上经常使用&#xff1f; 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「单片机的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿…