Dart中的对象都继承自 Object 类,单继承(extend关键字)。Dart与Java、kotlin不同的是其无public、private、protected修饰符,默认public ,通过在属性名、方法名前加 _下划线 来定义是否私有。
实现一个简单的类
class Student {
//默认public
final String name;
//默认public
final int age;
Student(this.name, this.age);
@override
bool operator ==(Object other) {
return identical(this, other) ||
other is Student &&
runtimeType == other.runtimeType &&
name == other.name &&
age == other.age;
}
@override
int get hashCode => name.hashCode ^ age.hashCode;
}
import 'package:gsy_flutter_demo/model/Student.dart';
main() {
var stu = Student("Jack", 18);
stu.name;
stu.age;
}
在属性名、方法名前加 _下划线 来定义私有属性。
class Person {
String _name = "jack";
int _age = 18;
}
定义私有属性和方法的类需要抽离放到一个单独的文件或者模块中。否则不会生效,例如写在同一个文件中,仍然可以访问私有属性。
class Person {
String _name = "jack";
int _age = 18;
}
main() {
var person = Person();
person._name;
person._age;
}
类定义&使用
与Java、Kotlin一样,使用 class 关键字定义一个类。实例化可以使用new关键字创建,也可以省略。
class Student {
final String name;
final int age;
Student(this.name, this.age);
@override
bool operator ==(Object other) {
return identical(this, other) ||
other is Student &&
runtimeType == other.runtimeType &&
name == other.name &&
age == other.age;
}
@override
int get hashCode => name.hashCode ^ age.hashCode;
}
var stu = Student("Jack", 18);
var stu2 = Student("Mike", 20);
构造函数
构造函数有四种形式:类名构造函数、命名构造函数、常量构造函数、工厂构造函数。
定义一个类,默认会有一个 无参构造函数,如果有父类,还会调用父类的无参构造函数。
类名构造函数
Student(this.name, this.age);
命名构造函数(类名.修饰符 定义的函数)
Student.create(String name) : this(name, 20);
注意:命名构造函数不可继承。
常量构造函数
如果类创建的对象不会改变,就可以在编译期就创建这个常量实例,并定义一个常量构造函数,并且确保所有成员变量都是final的。
//常量构造函数
const Student(this.name, this.age);
工厂构造函数
工厂构造函数,构造函数私有,使用 factory 关键字进行定义,根据不同情况创建不同的对象。
class Fruit {
final double price;
final int weight;
final String name;
Fruit._(this.price, this.weight, this.name);
//宸ュ巶鏋勯€犲嚱鏁版病鏈夎闂潈闄?
factory Fruit(String name) {
if (name == 'apple') {
return Fruit._(12, 5, name);
} else if (name == 'pear') {
return Fruit._(15, 5, name);
}
return Fruit._(100, 100, name);
}
get/set修饰符
class Fruit {
final double price;
final int weight;
final String name;
Fruit._(this.price, this.weight, this.name);
//宸ュ巶鏋勯€犲嚱鏁版病鏈夎闂潈闄?
factory Fruit(String name) {
if (name == 'apple') {
return Fruit._(12, 5, name);
} else if (name == 'pear') {
return Fruit._(15, 5, name);
}
return Fruit._(100, 100, name);
}
int? get fruitWeight => weight;
set price(double price) {
this.price = price;
}
对象操作符
类型强转 as
Fruit apple = Fruit("apple");
int weight = (apple as Fruit).fruitWeight ?? 0;
类型判断 is
if (apple is Fruit) {
print("apple");
}
级联操作 ..
apple
..price = 100.0
..weight = 100
..name = "Fruit";
class Fruit {
final double price;
late final int weight;
late final String name;
Fruit._(this.price, this.weight, this.name);
factory Fruit(String name) {
if (name == 'apple') {
return Fruit._(12, 5, name);
} else if (name == 'pear') {
return Fruit._(15, 5, name);
}
return Fruit._(100, 100, name);
}
int? get fruitWeight => weight;
set price(double price) {
this.price = price;
}
}
main() {
Fruit apple = Fruit("apple");
int weight = (apple as Fruit).fruitWeight ?? 0;
if (apple is Fruit) {
print("apple");
}
apple
..price = 100.0
..weight = 100
..name = "Fruit";
继承
子类使用 extends 关键字继承父类,子类会继承父类的属性和方法 (构造方法除外),使用 super 关键字调用父类属性/方法,或者给父类构造方法传参。
class Animal {
late String name;
late int type;
Animal(this.name, this.type);
}
class Tiger extends Animal {
int weight;
Tiger(super.name, super.type, this.weight);
}
接口和抽象类
接口的作用:解决多继承的二义性问题。即指的是多继承中方法和属性名称的冲突,编译器无法确定使用哪个父类的方法和属性。在Dart中,无interface关键字,所有类都被隐式定义成一个接口,任何类都可以作为接口被实现。Dart解决多继承、实现的二义性问题:子类必须将父类中所有属性和方法全部重写。
接口简单Demo
class DemoA {
int num;
DemoA(this.num);
void printDemo() => print("DemoA");
}
class DemoB {
int num;
DemoB(this.num);
void printDemo() => print("DemoB");
}
class DemoC implements DemoA, DemoB {
@override
int num = 6;
@override
void printDemo() {
print("DemoC");
}
}
注意:Java中的限制:接口中只能定义抽象成员和方法,且强制子类必须实现。
抽象类简单Demo
Dart中的抽象类不能被实例化,但可以包含 抽象方法 和 非抽象方法。
abstract class DemoA {
String demoName;
DemoA(this.demoName);
void doA();
void showA();
void printA() {
print("DemoA");
}
}
abstract class DemoB {
String demoBName = "DemoB";
void doDemoB();
void showDemoB();
void printDemoB() {
print("DemoB");
}
}
class RealDemo implements DemoA, DemoB {
@override
String demoBName = "RealDemo";
@override
String demoName = "RealDemo";
@override
void doA() {}
@override
void doDemoB() {}
@override
void printA() {}
@override
void printDemoB() {}
@override
void showA() {}
@override
void showDemoB() {}
}
class RealDemo extends DemoA implements DemoB {
@override
String demoBName = "demoBName";
RealDemo(super.demoName);
@override
void doA() {}
@override
void doDemoB() {}
@override
void printDemoB() {}
@override
void showA() {}
@override
void showDemoB() {}
}
Mixins
Dart中使用with关键字,将一个类的功能添加到另一个类中 (该类可以复用其中的方法和属性),从而能实现多继承。mixin 关键字来定义一个混入类。
mixin Run {
void run() => print("run");
}
class Animal {}
mixin Swim on Animal {
void swim() => print("swim");
}
class Tiger with Run {}
class Fish extends Animal with Swim, Run {
}
main() {
var fish = Fish();
fish.swim();
fish.run();
var tiger = Tiger();
tiger.run();
}
swim
run
run
注意: on子句 指定该mixin可以混入的类类型,只能混入到继承了Animal的类中。
枚举和密封类
Dart使用enum关键字定义枚举类型,枚举中的成员都有一个对应的索引值(这个值从0开始)。
枚举简单Demo
enum VALUE { VALUE_A, VALUE_B, VALUE_C }
main() {
for (var elemntValue in VALUE.values) {
print(elemntValue);
}
}
VALUE.VALUE_A
VALUE.VALUE_B
VALUE.VALUE_C
枚举支持 扩展方法
enum VALUE { VALUE_A, VALUE_B, VALUE_C }
extension VALUE_OPERATE on VALUE {
static VALUE getValueByIndex(int index) => VALUE.values[index];
}
main() {
var value = VALUE_OPERATE.getValueByIndex(1);
print(value);
}
VALUE.VALUE_B
增强型枚举
enum Month {
January(str: "January", num: 1),
February(str: "February", num: 1),
March(str: "March", num: 1),
April(str: "April", num: 1),
May(str: "May", num: 1),
June(str: "June", num: 1),
July(str: "July", num: 1),
August(str: "August", num: 1),
September(str: "September", num: 1),
October(str: "October", num: 1),
November(str: "November", num: 1),
December(str: "December", num: 1);
const Month({required this.str, required this.num});
final String str;
final int num;
}
main() {
print(Month.December.str);
}
December
密封类
与Kotlin类似,使用 sealed 关键字进行修饰,用于限制类的结构层次结构。
sealed class Status {}
class StatusA extends Status {}
class StatusB extends Status {}
class StatusC extends Status {}
String getStatusStr(Status status) {
return switch (status) {
StatusA() => "StatusA",
StatusB() => "StatusB",
StatusC() => "StatusC"
};
}