七.类 class
7.1. 类的定义
- 定义类用class关键字
- 类通常有两部分组成:成员(member)和方法(method)。
- dart没有public,private等关键字,使用下划线“_”来区分公有参数私有参数。
class 类名 {
类型 成员名;
返回值类型 方法名(参数列表) {
方法实现
}
}
- 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);
}
- 命名构造方法
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
}
- 初始化列表 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);
- 重定向构造方法
//重定向构造方法
class Person {
String name;
int age;
Person(this.name,this.age);
//重定向
Person.withName(String nameStr) : this(nameStr, 10);
}
- 常量构造方法
拥有常量构造方法的类中,所有的成员变量必须是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
- 工厂构造方法(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
- 单例模式
//写法一
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
网友评论