1、类的创建
//创建类
class CoustomClassOne {
String name = "历史";
int age = 18;
void getClassInfo() {
print("${this.name} ----- ${this.age}");
}
void setClassInfo(int age) {
this.age = age;
}
}
//使用
void main() {
//普通使用
var classOne = CoustomClassOne();
classOne.getClassInfo();
//级联调用
// CoustomClassOne p = CoustomClassOne();
// p
// ..name = "王五"
// ..age = 22
// .. getClassInfo();
}
1、默认初始化函数
class CustomClassTwo {
// String name = "";
// int age = 0;
// CustomClassTwo(String name, int age) {
// this.name = name;
// this.age = age;
// }
late String name;
late int age;
CustomClassTwo(this.name, this.age);
}
//使用
void main() {
CustomClassTwo ppp = CustomClassTwo("张三", 30);
print("name: ${ppp.name} ----- age: ${ppp.age}");
}
2、命名构造函数
class CustomClassThree {
late String name;
late int age;
//初始化函数,只能有一个
CustomClassThree(String name, int age);
//命名初始化函数,可以有多个,但函数名不能相同
CustomClassThree.setInfo(this.name, this.age);
// CustomClassThree.setInfo(this.name);
CustomClassThree.setInfoName(this.name);
CustomClassThree.setInfoAge(this.age);
}
//使用
void main() {
CustomClassThree three = CustomClassThree("wangwu", 44);
print(three);
CustomClassThree three2 = CustomClassThree.setInfo("liliu", 54);
print(three2);
CustomClassThree three3 = CustomClassThree.setInfoName("zhangsan");
print(three3);
CustomClassThree three4 = CustomClassThree.setInfoAge(32);
print(three4);
}
3、重定向构造函数
有时构造函数的唯一目的是重定向到同一个类中的另一个构造函数。重定向构造函数的函数体为空,构造函数的调用在冒号 (:) 之后。
class Point {
num x, y;
// 类的主构造函数。
Point(this.x, this.y);
// 指向主构造函数
Point.alongXAxis(num x) : this(x, 0);
}
4、常量构造函数
如果该类生成的对象是固定不变的,那么就可以把这些对象定义为编译时常量。为此,需要定义一个 const 构造函数,并且声明所有实例变量为 final。
class ImmutablePoint {
static final ImmutablePoint origin = const ImmutablePoint(0, 0);
final num x, y;
const ImmutablePoint(this.x, this.y);
}
5、工厂构造函数
当执行构造函数并不总是创建这个类的一个新实例时,则使用 factory 关键字。
class Logger {
final String name;
bool mute = false;
// 从命名的 _ 可以知,
// _cache 是私有属性。
static final Map<String, Logger> _cache =
<String, Logger>{};
factory Logger(String name) {
if (_cache.containsKey(name)) {
return _cache[name];
} else {
final logger = Logger._internal(name);
_cache[name] = logger;
return logger;
}
}
Logger._internal(this.name);
void log(String msg) {
if (!mute) print(msg);
}
}
注: 工厂构造函数无法访问 this
6、get set 方法
class Rectangle {
num left, top, width, height;
Rectangle(this.left, this.top, this.width, this.height);
// 定义两个计算属性: right 和 bottom。
num get right => left + width;
set right(num value) => left = value - width;
num get bottom => top + height;
set bottom(num value) => top = value - height;
}
void main() {
var rect = Rectangle(3, 4, 20, 15);
assert(rect.left == 3);
rect.right = 12;
assert(rect.left == -8);
}
7、初始化时默认赋值
class CustomClassFive {
late String name;
late int age;
CustomClassFive()
: name = "张三",
age = 22 {
print("name: ${this.name} ----- age: ${this.age}");
}
}
//使用
void main() {
CustomClassFive five = CustomClassFive();
}
2、继承(extends)
1、静态变量和静态方法
class CustomClass {
static String name = "立式";
static int age = 20;
// String name = "立式";
// int age = 20;
static void getInfo() {
print("name: ${name} ----- age: ${age}");
}
}
//使用
void main(List<String> args) {
print(CustomClass.name);
CustomClass.name = "王五";
print(CustomClass.name);
CustomClass.getInfo();
}
2、extends
//父类
class CustomSuperClass {
late String name;
late int age;
CustomSuperClass(this.name, this.age);
void printInfoFunc() {
print("superClass: name: ${name} ----- age: ${age}");
}
}
//子类
class CustomSubClass extends CustomSuperClass {
late String sex;
CustomSubClass(super.name, super.age, this.sex);
@override
void printInfoFunc() {
super.printInfoFunc();
// TODO: implement printInfoFunc
print(
"subClass override name: ${this.name} -- age: ${this.age} -- sex: ${this.sex}");
}
void run() {
print(
"subClass-- name: ${this.name} -- age: ${this.age} -- sex: ${this.sex}");
}
}
//使用
void main(List<String> args) {
CustomSubClass subClass = CustomSubClass("张三", 20, "male");
subClass.printInfoFunc();
subClass.run();
}
3、noSuchMethod()
当代码尝试使用不存在的方法或实例变量时,通过重写 noSuchMethod() 方法,来实现检测和应对处理。
class A {
// 如果不重写 noSuchMethod,访问不存在的实例变量时会导致 NoSuchMethodError 错误。
@override
void noSuchMethod(Invocation invocation) {
print('You tried to use a non-existent member: ' +
'${invocation.memberName}');
}
}
3、抽象类(abstract)
使用 abstract
修饰符来定义抽象类,抽象类不能实例化。抽象类通常用来定义接口以及部分实现。(如果希望抽象类能够被实例化,那么可以通过定义一个工厂构造函数来实现)
//抽象类
abstract class Animal {
eat();
run();
void printInfo() {
print("抽象类里面的普通方法");
}
}
//实现类
class Dog extends Animal {
@override
eat() {
// TODO: implement eat
print("狗东西");
// throw UnimplementedError();
}
@override
run() {
// TODO: implement run
print("四条腿");
// throw UnimplementedError();
}
}
class Cat extends Animal {
@override
eat() {
// TODO: implement eat
print("猫南北");
// throw UnimplementedError();
}
@override
run() {
// TODO: implement run
print("也是四条腿");
// throw UnimplementedError();
}
}
//使用
void main(List<String> args) {
Dog d = Dog();
// d.eat();
// d.run();
// d.printInfo();
d
..eat()
..run()
..printInfo();
Cat c = Cat();
// c.eat();
// c.run();
// c.printInfo();
c
..eat()
..run()
..printInfo();
}
4、接口(implements)
每个类都隐式的定义了一个接口,接口包含了该类所有的实例成员及其实现的接口。如果要创建一个 A 类,A 要支持 B 类的 API ,但是不需要继承 B 的实现,那么可以通过 A 实现 B 的接口。一个类可以通过 implements 关键字来实现一个或者多个接口,并实现每个接口要求的 API。
extends 和 implements 的区别
1、extends 用于继承;implements 用于定义接口。
2、extends 即要复用抽象类里面的方法,又要把抽象类当做标准来约束实用类;implements 只是把抽象类当做标准来约束实用类。
示例
构建数据库 mysql,mssql,mongodb
//抽象类
abstract class DataBase {
late String baseURL;
add(String obj);
delete(String obj);
update(String obj);
read(String obj);
}
//mysql
class Mysql implements DataBase {
@override
late String baseURL;
@override
add(String obj) => print("Mysql 中增加数据" + obj);
@override
delete(String obj) => print("Mysql 中删除数据" + obj);
@override
read(String obj) => print("Mysql 中读取数据" + obj);
@override
update(String obj) => print("Mysql 中更改数据" + obj);
}
//mssql
class Mssql implements DataBase {
@override
late String baseURL;
@override
add(String obj) {
// TODO: implement add
// throw UnimplementedError();
print("Mssql 中增加数据" + obj);
}
@override
delete(String obj) {
// TODO: implement delete
// throw UnimplementedError();
print("Mssql 中删除数据" + obj);
}
@override
read(String obj) {
// TODO: implement read
// throw UnimplementedError();
print("Mssql 中读取数据" + obj);
}
@override
update(String obj) {
// TODO: implement update
// throw UnimplementedError();
print("Mssql 中更改数据" + obj);
}
}
//mongodb
class Mongodb implements DataBase {
@override
late String baseURL;
@override
add(String obj) => print("Mongodb 中增加数据" + obj);
@override
delete(String obj) => print("Mongodb 中删除数据" + obj);
@override
read(String obj) => print("Mongodb 中读取数据" + obj);
@override
update(String obj) => print("Mongodb 中更改数据" + obj);
Mongodb(this.baseURL);
}
//使用
void main(List<String> args) {
Mysql my = Mysql();
my.baseURL = "MYXXXXXXXXXX";
my.add(my.baseURL);
my.delete(my.baseURL);
my.update(my.baseURL);
my.read(my.baseURL);
Mssql ms = Mssql();
ms.baseURL = "MSYYYYYYYYYY";
ms.add(ms.baseURL);
ms.delete(ms.baseURL);
ms.update(ms.baseURL);
ms.read(ms.baseURL);
Mongodb mo = Mongodb("MOZZZZZZZZZZ");
// mo.baseURL = "MOZZZZZZZZZZ";
mo.add(mo.baseURL);
mo.delete(mo.baseURL);
mo.update(mo.baseURL);
mo.read(mo.baseURL);
}
5、混入(mixins):实现类似多继承功能
为类添加功能。Mixin 是复用类代码的一种途径,复用的类可以在不同层级,之间可以不存在继承关系。通过 with 后面跟一个或多个混入的名称,来使用 Mixin。
实现条件:
1、只能继承自 object 类。
2、不能有构造函数。
3、一个类可以 mixins 多个 mixins 类。
4、mixins 不是继承,也不是接口,而是一种新特性。
示例
mixin ClassA {
String infoA = "infoA";
// printInfo(){
// print("printInfoA");
// }
printInfoA() => print("printInfoA");
}
mixin ClassB {
String infoB = "infoB";
printInfoB() => print("printInfoB");
}
class ClassC with ClassA, ClassB {}
void main(List<String> args) {
var c = ClassC();
print(c.infoA);
print(c.printInfoA());
print(c.infoB);
print(c.printInfoB());
}
//继承
abstract class ClassD {
String infoD = "infoD";
printInfoD() => print("printInfoD");
}
class ClassC extends ClassD with ClassA, ClassB {}
void main(List<String> args) {
var c = ClassC();
print(c.infoA);
print(c.printInfoA());
print(c.infoB);
print(c.printInfoB());
print(c.infoD);
print(c.printInfoD());
}
注:
1、若 with 后面的类 ClassA,ClassB 中有同名方法,则后加入的方法会执行。
2、可以使用 on 来指定哪些类可以使用 mixin 类。当声明一个 mixin 时,on 后面的类是使用这个 mixin 的父类约束。也就是说一个类若是要 with 这个 mixin,则这个类必须继承或实现这个 mixin 的父类约束。
mixin ClassE on ClassD {}
6、泛型
解决代码复用和类型校验。
1、泛型方法
T getRuturn<T>(T value) => value;
A getReturn1<A>(A value) => value;
AB getReturn2<AB>(AB value) => value;
fan getReturn3<fan>(fan value) => value;
b getReturn4<b>(b value) => value;
void main(List<String> args) {
print(getRuturn<String>("哈哈哈"));
print(getRuturn<int>(12345));
print(getReturn1<String>("啊啊啊啊啊"));
print(getReturn1<int>(98765655));
print(getReturn2<String>("略略略..."));
print(getReturn2<int>(6666666));
}
注:泛型符号可以用任何字母,但不可以是汉字、数字。
2、泛型类
//泛型类
class Mylist<T> {
List l = <T>[];
add(T value) => this.l.add(value);
getList() => l;
}
void main(List<String> args) {
Mylist l = Mylist();
l.add("哈哈");
l.add(12345);
l.add(true);
print(l.getList());
}
//指定类型
void main(List<String> args) {
Mylist l = Mylist<String>();
l.add("123");
l.add("456");
l.add("789");
print(l.getList());
}
3、泛型接口
//泛型接口
abstract class Cache<T> {
getByKey(String key);
setByKey(String key, T value);
}
//接口实现
class FileCache<T> implements Cache<T> {
@override
getByKey(String key) {
// TODO: implement getByKey
// throw UnimplementedError();
print("FileCache -- getByKey -- key: " + key);
}
@override
setByKey(String key, T value) {
// TODO: implement setByKey
// throw UnimplementedError();
print("FileCache -- setByKey -- key: " + key + "value: ${value}");
}
}
class MemoryCahce<T> implements Cache<T> {
@override
getByKey(String key) => print("MemoryCahce -- getByKey -- key: " + key);
@override
setByKey(String key, T value) =>
print("MemoryCahce -- setByKey -- key: " + key + "value: ${value}");
}
void main(List<String> args) {
FileCache file = FileCache();
file.setByKey("哈哈", 12345);
file.getByKey("咯咯咯");
MemoryCahce mem = MemoryCahce<String>();
mem.setByKey("嘻嘻", "jjjjj");
mem.getByKey("叽叽叽");
}
7、异步
async:让方法异步执行。(如果要使用 async 关键字,则必须要使用 await 关键字)。
await:等待异步方法执行完成。
void main(List<String> args) async {
var t = await testAsync();
print(t);
}
//异步方法
testAsync() async {
return "异步方法";
}
网友评论