[Flutter]足够入门的Dart语言系列之面向对象:类的定义详解、成员和实例使用

简介: 类表示的是分类,一类问题或事物,它是对具体或现实世界的抽象。比如动物类、犬科动物类、猫科动物类、房子类、数学类,类是具体事物的描述,它不是指具体的某个动物、某栋房子、某个数学题,而是对它们的概括...

表示的是分类,一类问题或事物,它是对具体或现实世界的抽象。比如动物类犬科动物类猫科动物类房子类数学类等,类是具体事物的描述,它不是指具体的某个动物、某栋房子、某个数学题,而是对它们的概括。

上面的定义虽然比较正式化,但它却能明确的表达编程中的含义,一个可以描述这个事物,另一个就可以描述另一个事物(只是抽象程度可能有所不同),由此可以推出,可以用描述任何事物。可以抽象现实中任何事物(包括非现实中的),的具体化就是一个具体的特指的对象,任何事物可以用描述为一个对象,这就是面向对象的开发思想。

不仅描述数据或状态,通常还包含行为或功能,用来"完整"的表示一类事物,完成指定的功能逻辑。

类class详细介绍

类的定义

class关键字用来定义一个,后面的标识符表示类的名称。名称后面,通过 {} 表示类定义的作用域,在其中可以定义类的 成员变量成员方法

class ClassName{
    // 类中的成员
}

比如我们定义一个MyAdd实现加法功能的类。

class MyAdd{
    double a=0;
    double b=0;

    double sum(){
        return a+b;
    }
}

类的实例化

定义了类就需要使用,使用类就要创建类对应的具体的对象。

创建对象的过程称为类的实例化,对象是类的一个实例。

var myClassName=ClassName();

比如,我们创建加法类MyAdd的实例,并使用其中的成员:

var myadd=MyAdd();

myadd.a=10;
print(myadd.sum()); // 10
dart提供可选的 new关键字来创建对象: var myClassName=new ClassName();

成员方法

成员变量表示类有哪些数据或状态;成员方法表示类有哪些功能或行为。

MyAdd类的成员方法sum用于实现计算和的功能。通过.进行方法的调用。

var sum=myadd.sum();

成员方法的作用就是对类的逻辑功能的封装,可以达到直接调用,使用对应功能的目的。

构造函数

声明一个与类名一样的函数即可声明一个构造函数。构造函数的作用是用于创建一个类的实例,实现类的实例化,创建一个具体的对象。

构造函数的特定

构造函数是一个特殊的函数:

  1. 构造函数在声明时无返回值。
  2. 构造函数可以没有方法体。
  3. 在参数列表中可以通过 this.成员 ,为成员变量进行赋值。
  4. 没有显式声明构造函数时,默认自动生成一个无参、无方法体的构造函数。

比如上面的MyAdd类,其对应的完整类定义如下,两者等同:

class MyAdd{
    double a=0;
    double b=0;

    MyAdd();
    // ...
}

声明一个有参的构造函数,函数体内实现对属性的赋值。

class MyAdd{
    double a=0;
    double b=0;

    MyAdd(double a,double b){
        this.a=a;
        this.b=b;
    }
    // ...
}
this关键字引用当前实例,指代的是当前对象。

上面使用this是因为参数和成员变量有命名冲突,为了区分才显式的使用this。如果没有冲突,通常不需要指定this

使用时,构造函数需要传入正确的参数。

var myadd = MyAdd(10,6);

参数的初始化形式

构造函数的参数有简化的初始化形式,而不用在构造函数体内进行赋值。

如下,这是为实例变量赋值简化的语法糖:

class MyAdd {
  double a;
  double b;

  MyAdd(this.a,this.b);
}

初始化列表

构造函数可以在执行函数体之前,初始化实例变量。

MyAdd(double a, double b)
    : this.a=a,
    this.b=b;

通过在构造函数的右括号有加:,后面跟随对变量的赋值,多个变量之间用逗号分隔。

在开发模式下,HIA可以在初始化列表中使用 assert 来验证输入数据

MyAdd(this.a, this.b): assert(a>0&&b>0){
  print('参数需要大于0');
}

构造函数的参数

构造函数的参数和普通函数参数一样,可以是位置参数、可选位置、命名参数等。

如下,使用命名参数对_name成员变量赋值。

class MyAdd {
  double a;
  double b;
  String? _name;

  MyAdd(this.a,this.b,{String? name}):_name=name;
  //...
}

使用方法:

var add1=MyAdd(1,2);
var add2=MyAdd(1,2,name:"add2");

和普通函数的调用一样。

类中的非空类型的成员变量,必须进行初始化,要么在声明时初始化,要么在构造函数中进行初始化。

命名参数是可选的,所以,要么是可空的类型,要么需要提供默认值,否则,就要使用required关键字,保证参数是必须的,实现成员的初始化。

class MyAdd {
  double a;
  double b;
  String _name;

  MyAdd(this.a,this.b,{String name="MyAdd"}):_name=name;
}

Dart中大量使用了命名参数的形式,将MyAdd构造函数改为命名参数。

class MyAdd {
  double a;
  double b;
  String? _name;

  MyAdd({
    this.a=0,
    required this.b,
    String? name
  }):_name=name;
  // ...
}

使用形式如下:

var add1=MyAdd(b:2);
var add2=MyAdd(a:10,b:15,name:"add2");

命名构造函数

在Dart中,上面所示的构造函数形式被称为“生成式构造函数”( generative constructor)。

使用命名式构造函数(Named constructor),可以为一个类声明多个构造函数,用于以不同形式创建对象。通过命名的方式,表达更明确的意图。

以一个表示向量的类为例:

import 'dart:math' as math;

class Vec2 {
  double x;
  double y;

  Vec2(this.x, this.y);

  Vec2.polar(double length, double rad)
      : x = length * math.cos(rad),
        y = length * math.sin(rad);
}

通常,都是使用Vec2(this.x, this.y)坐标系中的坐标来构建向量;

除此之外,还可以使用极坐标来获取,即命名构造函数Vec2.polar(double length, double rad),通过长度和角度来创建向量。

命名构造函数通过类名.构造名的形式定义,可以定义多个不同含义或使用场景命名的构造函数。

重定向构造函数

有时,类中的构造函数仅用于调用类中其它的构造函数,此时该构造函数没有函数体,在函数签名后使用:,通过this指定需要重定向的其他构造函数。

本质上,是构造函数的重新利用,避免写相关的重复代码。

class Vec2 {
  double x;
  double y;

  Vec2(this.x, this.y);

  Vec2.alongXAxis(double x) : this(x, 0);
}

成员变量(对象属性)的 Getter 和 Setter

类中的变量称为成员变量,也称为对象的属性,或,实例变量。通过对象可以访问和修改其属性。

比如MyAddab成员变量、Vec2xy成员变量。

除了像正常的变量一样定义和使用成员变量,还可以使用 GetterSetter 实现对象属性的读写方法。

默认,实例对象的每一个属性都有一个隐式的 Getter 方法,如果为非 final 属性的话还会有一个 Setter 方法。

所有未初始化的实例变量其值均为 null。

可以使用 get 和 set 关键字显式的定义 Getter 和 Setter 方法。get/set属性本质上是特殊的方法。

比如,为Vec2添加一个只读的length属性。

import 'dart:math' as math;

class Vec2 {
  double x;
  double y;

  Vec2(this.x, this.y);

  double get length => math.sqrt(x * x + y * y);
  // 等同
  // double get length{
  //   return math.sqrt(x * x + y * y);
  // }
}

通常 Getter 和 Setter 都写为箭头函数的形式。

下面以一个正方形的类为例,看一下get、set两者的具体使用:

class Rectangle {
  double left, top, width, height;

  Rectangle(this.left, this.top, this.width, this.height);

  // 定义两个计算属性: right 和 bottom.
  double get right => left + width;
  set right(double value) => left = value - width;
  
  double get bottom => top + height;
  set bottom(double value) => top = value - height;
}

get 关键字用于获取属性值,此方法不能传参;set 关键字用于向属性设置值,此方法只能传入一个参数(即属性赋值时=右边的值)。

只有get方法的属性称为只读属性;只有set方法的属性称为只写属性。

类变量和方法(静态成员)

使用static关键字可以声明静态成员,静态变量和静态方法是属于类的,而不是类创建的对象,因此,也被称为类变量和类方法。

静态成员由 类 本身直接访问和修改,不依附于 对象。

下面定义一个Person类,其中静态变量dynasty表示朝代。

class Person {
  String name;
  static String dynasty = "";

  Person(this.name);

  void info() {
    print('$name是$dynasty人');
  }
}

通过类名.静态成员名直接访问或修改静态成员。

Person.dynasty = "唐朝";
print(Person.dynasty); // 唐朝

普通成员方法可以直接访问静态成员,但是静态成员中不能访问实例方法或属性。

下面通过Person对象的info方法直接访问静态变量:

Person.dynasty = "唐朝";

var p = Person('李白');
p.info(); // 李白是唐朝人

静态成员是属于类的,实例对象共享同一个静态成员,通过类修改静态成员后,所有的对象都能访问到。

这是静态成员变量的特点,它不依赖于具体对象,是类本身的一种属性,是所有对象的公共属性或特性

下面,首先创建一些唐朝人,然后修改朝代,再创建一些宋朝人:

// 创建一些唐朝Person对象
Person.dynasty = "唐朝";
var p1 = Person('李白');
var p2 = Person('杜甫');
p1.info();
p2.info();


// 创建一些宋朝Person对象
Person.dynasty = "宋朝";
var p3 = Person('苏轼');
var p4 = Person('范仲淹');
p3.info();
p4.info();

// -------------------------
// 输出:
// 李白是唐朝人
// 杜甫是唐朝人
// 苏轼是宋朝人
// 范仲淹是宋朝人

static也可以修饰类的成员方法,和静态变量一样,静态方法也是属于类的,独立于具体的对象而存在。通过类名.静态方法名();进行调用。

比如下面的静态方法printDynasty,调用方式Person.printDynasty();

class Person {
  String name;
  static String dynasty = "";

  Person(this.name);

  void info() {
    print('$name是$dynasty人');
  }

  static void printDynasty() {
    print("现在朝代是: $dynasty");
  }
}

静态方法中不能访问实例变量或实例方法,因为实例成员属于对象,只用对象才能调用。而静态方法中是没有当前实例对象的。

如果在静态方法中访问实例成员将会报错。

类中的不可变成员

final关键字修饰的成员在声明后只能被赋值一次,在类中,通常用于构造函数中对其进行初始化赋值。此后,不允许被修改。

class Vec2 {
 final double x;
 final double y;

  Vec2(this.x, this.y);
}

修改final变量将会报错:

通常对于没有修改需求的成员变量使用final修饰,避免后续对其进行误操作,修改掉固定值。比如上面的Vec2对象,在创建后表示一个唯一的点,点对象创建后不允许修改。如果想要得到另一个点,需要创建一个新的Vec2对象。

const关键字用在类中,必须修饰静态成员,并且要在声明时初始化。

参考

相关文章
|
3月前
|
开发框架 Dart 前端开发
Flutter 是谷歌推出的一款高效跨平台移动应用开发框架,使用 Dart 语言,具备快速开发、跨平台支持、高性能、热重载及美观界面等特点。
Flutter 是谷歌推出的一款高效跨平台移动应用开发框架,使用 Dart 语言,具备快速开发、跨平台支持、高性能、热重载及美观界面等特点。本文从 Flutter 简介、特点、开发环境搭建、应用架构、组件详解、路由管理、状态管理、与原生代码交互、性能优化、应用发布与部署及未来趋势等方面,全面解析 Flutter 技术,助你掌握这一前沿开发工具。
153 8
|
5月前
|
Dart
如何在 Flutter 项目中使用 Dart 语言?
如何在 Flutter 项目中使用 Dart 语言?
153 58
|
3月前
|
Dart
flutter dart mixin 姿势
flutter dart mixin 姿势
|
4月前
|
搜索推荐
Flutter 中的 AnimationController 类
【10月更文挑战第18天】深入了解了 Flutter 中的 `AnimationController`类。它是构建精彩动画效果的重要基石,掌握它的使用方法对于开发具有吸引力的 Flutter 应用至关重要。
|
4月前
|
Dart 开发者 Windows
flutter:dart的学习
本文介绍了Dart语言的下载方法及基本使用,包括在Windows系统上和VSCode中的安装步骤,并展示了如何运行Dart代码。此外,还详细说明了Dart的基础语法、构造函数、泛型以及库的使用方法。文中通过示例代码解释了闭包、运算符等概念,并介绍了Dart的新特性如非空断言操作符和延迟初始化变量。最后,提供了添加第三方库依赖的方法。
49 12
|
4月前
|
开发框架 移动开发 Android开发
安卓与iOS开发中的跨平台解决方案:Flutter入门
【9月更文挑战第30天】在移动应用开发的广阔舞台上,安卓和iOS两大操作系统各自占据半壁江山。开发者们常常面临着选择:是专注于单一平台深耕细作,还是寻找一种能够横跨两大系统的开发方案?Flutter,作为一种新兴的跨平台UI工具包,正以其现代、响应式的特点赢得开发者的青睐。本文将带你一探究竟,从Flutter的基础概念到实战应用,深入浅出地介绍这一技术的魅力所在。
137 7
|
6月前
|
Kubernetes Cloud Native 搜索推荐
探索云原生技术:Kubernetes入门与实践打造个性化安卓应用:从零开始的Flutter之旅
【8月更文挑战第31天】云原生技术正改变着应用开发和部署的方式。本文将带你了解云原生的基石——Kubernetes,通过实际的代码示例,从安装到部署一个简单的应用,让你迅速掌握Kubernetes的核心概念和操作方法。无论你是初学者还是有一定经验的开发者,这篇文章都将成为你进入云原生世界的桥梁。
|
开发工具 Android开发 iOS开发
Flutter从入门到实战
版权声明:本文为博主原创文章,转载请注明出处http://blog.csdn.net/u013132758。 https://blog.csdn.net/u013132758/article/details/80474494 Flutter从入门到实战 Flutter概述   Flutter是一款移动应用程序SDK,一份代码可以同时生成iOS和Android两个高性能、高保真的应用程序。
2269 0
|
30天前
|
前端开发 Java 开发工具
【03】完整flutter的APP打包流程-以apk设置图标-包名-签名-APP名-打包流程为例—-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈 章节内容【03】
【03】完整flutter的APP打包流程-以apk设置图标-包名-签名-APP名-打包流程为例—-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈 章节内容【03】
75 18
【03】完整flutter的APP打包流程-以apk设置图标-包名-签名-APP名-打包流程为例—-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈 章节内容【03】
|
24天前
flutter开发中Use ‘const’ with the constructor to improve performance. Try adding the ‘const’ keyword to the constructor invocation.报错如何解决-优雅草卓伊凡
flutter开发中Use ‘const’ with the constructor to improve performance. Try adding the ‘const’ keyword to the constructor invocation.报错如何解决-优雅草卓伊凡
18 1

热门文章

最新文章

  • 1
    【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 2
    【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
  • 3
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 4
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
  • 5
    【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
  • 6
    【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
  • 7
    零基础构建即时通讯开源项目OpenIM移动端-Flutter篇
  • 8
    flutter3-dart3-dymall原创仿抖音(直播+短视频+聊天)商城app系统模板
  • 9
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 10
    【06】flutter完成注册页面-密码登录-手机短信验证-找回密码相关页面-并且实现静态跳转打包demo做演示-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
  • 1
    零基础构建即时通讯开源项目OpenIM移动端-Flutter篇
    51
  • 2
    flutter3-dart3-dymall原创仿抖音(直播+短视频+聊天)商城app系统模板
    34
  • 3
    【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    137
  • 4
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    35
  • 5
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
    70
  • 6
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    111
  • 7
    【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
    73
  • 8
    flutter开发中Use ‘const’ with the constructor to improve performance. Try adding the ‘const’ keyword to the constructor invocation.报错如何解决-优雅草卓伊凡
    18
  • 9
    【06】flutter完成注册页面-密码登录-手机短信验证-找回密码相关页面-并且实现静态跳转打包demo做演示-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
    25
  • 10
    【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
    116