当前位置: 首页 > news >正文

dart学习记录5(类、对象)

1.获取运行时对象类型

使用Object 属性的 runtimeType,它返回一个 Type 对象。

print('a 的类型是 ${a.runtimeType}');

⚠️警告

在测试对象的类型时建议使用object is Type比测试 object.runtimeType == Type 更稳定。

2.实例变量的声明

class Point {
  double? x; // 声明实例变量 x,初始值为 null。
  double? y; // 声明 y,初始值为 null。
  double z = 0; // 声明 z,初始值为 0。
}

所有实例变量都会生成一个隐式的 getter 方法。非final的实例变量,以及未初始化的late final实例变量,都会生成一个隐式的setter方法。

class Point {
  double? x; // 声明实例变量 x,初始值为 null。
  double? y; // 声明 y,初始值为 null。
}

void main() {
  var point = Point();
  point.x = 4; // 使用 x 的 setter 方法。
  assert(point.x == 4); // 使用 x 的 getter 方法。
  assert(point.y == null); // 默认值为 null。
}

在声明时初始化非 late 实例变量会在实例创建时设置值,在构造函数及其初始化列表执行之前。因此,非 late 实例变量的初始化表达式(= 之后的表达式)无法访问 this。

double initialX = 1.5;

class Point {
  // 可以访问不依赖 `this` 的声明:
  double? x = initialX;

  // 错误,在非 `late` 初始化器中无法访问 `this`:
  double? y = this.x;

  // 可以,在 `late` 初始化器中访问 `this`:
  late double? z = this.x;

  // 可以,`this.x` 和 `this.y` 是参数声明,不是表达式:
  Point(this.x, this.y);
}

实例变量可以是 final 的,在这种情况下它们必须被设置且仅设置一次。可以在声明时使用构造函数参数或者使用构造函数的初始化列表来初始化final类型的非late实例变量。

class ProfileMark {
  final String name;
  final DateTime start = DateTime.now();

  ProfileMark(this.name);	//使用构造函数参数,来初始化final类型的非late实例变量
  ProfileMark.unnamed() : name = '';	//使用构造函数的初始化列表,来初始化final类型的非late实例变量
}

如果您需要在构造函数体开始后为 final 实例变量赋值,可以使用以下方法之一:

  • 使用工厂构造函数。
  • 使用 late final,但要小心:没有初始值设定器的late final会为 API 添加一个 setter。

3.隐式接口

每个类都隐式地定义了一个接口,该接口包含该类的所有实例成员以及它所实现的任何接口的实例成员。如果你想创建一个支持类 B 的应用程序编程接口(API)但又不继承 B 的实现的类 A,那么类 A 应该实现 B 接口。

implements 关键字主要用于类实现接口

  • 概念:接口规定了一组方法的签名,不过不包含具体实现。类借助 implements 关键字来实现接口时,就必须实现接口里定义的所有方法

  • 使用方法:在类定义时,运用 implements 关键字,后面紧跟一个或多个接口名,若有多个接口,用逗号分隔。类需要实现接口中定义的所有方法。

  • 示例

// 定义一个接口
abstract class Animal {
  void eat();
  void sleep();
}

// 实现接口的类
class Dog implements Animal {
  
  void eat() {
    print('Dog is eating.');
  }

  
  void sleep() {
    print('Dog is sleeping.');
  }
}

void main() {
  Dog dog = Dog();
  dog.eat();
  dog.sleep();
}

在上述代码中,Animal 是一个接口,定义了 eat 和 sleep 方法。Dog 类使用 implements 关键字实现了 Animal 接口,并且实现了接口中定义的所有方法。

与 extends 的区别

  • extends:用于类的继承,一个类只能单继承,子类会继承父类的实现。
  • implements:用于实现接口,一个类可以实现多个接口,类需要自己实现接口中定义的所有方法

一个类通过在 implements 子句中声明一个或多个接口,然后提供这些接口所要求的 API 来实现它们。

以上来自AI的解释,下面是dart官方文档的
类通过在 implements 子句中声明一个或多个接口并提供接口所需的 API 来实现它们。例如:

// 一个 person类. 包含一个隐式接口greet().
class Person {
  // 在接口中,但仅在此类中可见.
  final String _name;

  // 不在接口中,因为这是一个构造函数.
  Person(this._name);

  // 在接口中.
  String greet(String who) => 'Hello, $who. I am $_name.';
}

// Person 接口的一个实现类.
class Impostor implements Person {
  String get _name => '';

  String greet(String who) => 'Hi $who. Do you know who I am?';
}

String greetBob(Person person) => person.greet('Bob');

void main() {
  print(greetBob(Person('Kathy')));	//你好,Bob。我是 Kathy
  print(greetBob(Impostor()));	//嗨 Bob。你知道我是谁吗?
}

4.类变量和方法

使用 static 关键字来实现类级的变量和方法。

  • 静态变量
    静态变量(类变量)对于类范围的状态和常量非常有用
class Queue {
  static const initialCapacity = 16;
  // ···
}

void main() {
  assert(Queue.initialCapacity == 16);	//静态成员/方法无需创建实例,直接访问/调用
}

静态变量只有在使用时才会被初始化

  • 静态方法
    静态方法(类方法)不作用于实例,因此无法访问 this。但是,它们可以访问静态变量。如下例所示,您直接在类上调用静态方法:
import 'dart:math';

class Point {
  double x, y;
  Point(this.x, this.y);

  static double distanceBetween(Point a, Point b) {
    var dx = a.x - b.x;
    var dy = a.y - b.y;
    return sqrt(dx * dx + dy * dy);
  }
}

void main() {
  var a = Point(2, 2);
  var b = Point(4, 4);
  var distance = Point.distanceBetween(a, b);
  assert(2.8 < distance && distance < 2.9);
  print(distance);
}

⚠️注意

对于常用或广泛使用的工具和功能,考虑使用顶级函数,而不是静态方法。
您可以将静态方法用作编译时常量。例如,您可以将静态方法作为参数传递给常量构造函数。

相关文章:

  • 练习-班级活动(map存储键值对)
  • hexo+butterfly博客功能完善和美化(三)---评论功能载入
  • Transformer-GRU、Transformer、CNN-GRU、GRU、CNN五模型多变量回归预测
  • 爱普生晶振FC2012AA汽车ADAS主控制系统的理想选择
  • 代码随想录刷题day50|(回溯算法篇)131.分割回文串▲
  • zephyr-中国跨国并购数据(1997-2024.3.8)
  • C# System.Text.Encoding 使用详解
  • 支持向量机(SVM):从入门到精通的机器学习利器
  • 多模态大模型常见问题
  • 模型整合-cherry studio+mysql_mcp_server服务配置
  • Flink实战教程从入门到精通(基础篇)(一)Flink简介
  • 从PGC到AIGC:海螺AI多模态内容生成系统架构一站式剖析
  • VS010生成可由MATLAB2016调用的DLL文件方法
  • 实现MySQL的横向扩展
  • kubernetes pod控制器 DaemonSet
  • 第P8周:YOLOv5-C3模块实现
  • 【漫话机器学习系列】152.ReLU激活函数(ReLU Activation Function)
  • ARM 汇编基础
  • FPGA中串行执行方式之状态机
  • AWS CDK实战:用代码重新定义云基础设施部署
  • 首次带人形机器人走科技节红毯,傅利叶顾捷:没太多包袱,很多事都能从零开始
  • 中国物流集团等10家央企11名领导人员职务任免
  • 小米汽车机盖门陷谈判僵局,车主代表称小米表示“退订会造成崩塌”
  • 网易一季度净利增长三成,丁磊:高度重视海外游戏市场
  • 广西等地旱情缓解,水利部针对甘肃启动干旱防御Ⅳ级响应
  • 钕铁硼永磁材料龙头瞄准人形机器人,正海磁材:已向下游客户完成小批量供货