文章目录
重要的事情说三遍:
dart中每个类除了object外只能有一个基类(或者叫超类)
dart中每个类除了object外只能有一个基类(或者叫超类)
dart中每个类除了object外只能有一个基类(或者叫超类)
dart类的有一个不一样的地方就是类属性和类方法:
通常我们都是实例化对象后进行调用的,但是dart类本身也是一种对象,所以使用类名也可以直接进行调用
比如
class people{
String name = "susuan";
func(){
print("hello world");
}
}
main(){
print(people.name);
people.func();
}
1.定义一个类
注意 和C++不一样的是 类的{}后面不用加分号“;”
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
}
简化后可写成
class Person {
String name;
int age;
// 在构造方法中初始化成员变量时,可使用如下写法简化
Person(this.name, this.age);
}
如需处理其他变量时,也可单独对其操作
class Person {
String name;
int age;// 如需处理其他变量时,也可单独对其操作
Person(this.name, this.age, String address){
print(address);
}
}
如需处理其他变量时,也可单独对其操作
class Person {
String name;
int age;// 如需处理其他变量时,也可单独对其操作
Person(this.name, this.age, String address){
print(address);
}
}
2.命名构造方法
不支持构造方法重载,但有命名构造方法
可以快速构建你想要的实例对象
class Person {
String userName;
int age;
Person(this.userName, this.age);
// 命名构造方法
Person.fromData(Map data) {
this.userName = data['name'];
this.age = data['age'];
}
}
void main() {
// 使用命名构造方法创建对象
var p = new Person.fromData({
"name":"Bob",
"age":19
});
print(p.userName);
}
3.可以通过实现 getters 和 setters 来创建附加属性
也就是直接使用 get 和 set 关键词:
可以通过实现 getters 和 setters 来创建附加属性,使用get关键字定义getter或访问器。Setter或存取器是使用set关键字定义的。可以通过显式定义setter/getter来覆盖默认值。getter没有参数并返回一个值,setter只有一个参数但不返回值。
set是用来创建对象使用,get是输出的时候用的。
class Rectangle {
num left;
num top;
num width;
num height;
Rectangle(this.left, this.top, this.width, this.height);
// 定义两个计算属性: right and 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;
}
main() {
var rect = new Rectangle(3, 4, 20, 15);
assert(rect.left == 3);
rect.right = 12;
assert(rect.left == -8);
}
4.抽象类
书p53
抽象类实际就是一个接口,它是没有被实现的类。标识符是在class前加abstract就表明这个类是接口类。
接口中定义了未实现的方法告诉调用者,如果有类实现了这个接口,这个类(实现类)就拥有了接口所描述的功能。
实现的时候用implements来继承接口类
注意:一个类可以实现多个接口类
抽象类是不能被实例化的,子类继承抽象类时,必须实现全部抽象方法。
abstract class Base {
// 省略函数体即可定义抽象方法,不需加关键字
func1();
func2();
}
隐式接口(见53页)
实际上在Dart中,每个类都隐式的定义了一个包含所有实例成员的接口, 并且该类实现了这个接口
因此,如果我们想实现某个接口,但有又不想继承,则可以使用这种隐式接口机制。我们需要用到关键字implements
比如abstract的抽象类就可以放在新类中并使用implements进行实现
5.常量构造函数
如果想提供一个状态永远不变的对像,在Dart中,我们可以创建一个编译时常量对象,节省开销。
如果类提供的是状态不变的对象,那么可以把这些对象定义为编译时常量,实现这种功能可以定义const构造函数,且声明所有类的变量为final,如:
class ConstPoint {
final num x;
final num y;
// 使用const修构造方法
const ConstPoint(this.x, this.y);
// 编译时常量对象,需使用const来创建对象
// 常量如果是类级别的,请使用 static
static final ConstPoint origin = const ConstPoint(0, 0);
}
void main() {
print(ConstPoint.origin.x);
print(ConstPoint.origin.y);
}
6、静态方法、静态常量
static 关键字来实现类级别的变量和函数、类中的常量需要使用static const声明
静态成员不能访问非静态成员、非静态成员可以访问静态成员
class People{
static int age;
static void Say(){
print('hello!');
}
}
void main(){
People.age = 10;
People.Say();
}
7.工厂构造方法
当我们需要创建一个新的对象或者从缓存中取一个对象时,工厂构造方法就派上了用场。
注意:工厂构造函数不能用 this。
class Logger {
final String name;
// 创建一个静态Map做为缓存,
static final Map<String, Logger> _cache = <String, Logger>{};
// 定义一个命名构造方法,用下划线"_"修饰,将构造方法私有化
Logger._internal(this.name);
// 使用关键字factory修饰类同名构造方法
factory Logger(String name) {
if (_cache.containsKey(name)) {
return _cache[name];
} else {
// 调用命名构造方法创建新对象
final logger= new Logger._internal(name);
_cache[name] = logger; // 存入缓存
return logger;
}
}
}
void main() {
var uiLog = new Logger('UI');
var eventLog = new Logger('event');
}
8.构造方法重定向
有时候一个构造方法会调动类中的其他构造方法来实例化,这时候可以使用构造方法重定向
class Point {
num x;
num y;
// 同名构造方法
Point(this.x, this.y);
// 命名构造方法重定向到同名构造方法,中间使用一个冒号
Point.alongXAxis(num x) : this(x, 0);
}
9.类的初始化列表
位于构造方法(而不是类前后)的小括号与大括号之间,在初始化列表之前需添加一个冒号
逗号分隔的一些赋值语句组成
适合用来初始化 final修饰的变量
调用是在构造方法之前
class Point {
final num x;
final num y;
final num distance;
Point(x, y)
: x = x,
y = y,
distance = sqrt(x * x + y * y){
print("这是构造方法");
}
}
void main() {
var p = new Point(2, 3);
print(p.distance);
}
10.运算符重写
格式:
类的返回值类型 operator 运算符(参数列表){
函数体
}
class Point {
int x;
int y;
Point(this.x, this.y);
// 使用operator关键字,为该类重载"+"运算符
Point operator +(Point p) {
return new Point(this.x + p.x, this.y + p.y);
}
// 为该类重载"-"运算符
Point operator -(Point p) {
return new Point(this.x - p.x, this.y - p.y);
}
}
void main(){
var p1 = new Point(1,5);
var p2 = new Point(7,10);
// 重载运算符后,类可以使用“+”、“-” 运算符操作
var p3 = p1 + p2;
var p4 = p2 - p1;
print("${p3.x}, ${p3.y}");
print("${p4.x}, ${p4.y}");
}
11.类的单继承
书55页
类的单继承要注意的几个点:
- 关键之是extends
- 是单继承
- 构造方法是不会继承的
- 但是可以用super方法调用父类的构造方法(小技巧比如父类是people我们就可以把super等价想象成people即可,比如peolpe的构造函数是people(){} 对吧,那么子类调用父类的构造方法就是super(){}是不是很清楚)
- 可以重写父类的方法,@override可以省略起到注释重写方法的作用
class Father {
myFunction(){
// do something
}
}
class Son extends Father {
@override//重写父类的函数
myFunction(){
super.myFunction();
// do something
}
}
12.mixin 混入(用with作为关键字)
见书58页
当我们的继承父类不是同一个的,同时子类里面需要实现同样的功能时,Mixin显得尤为重要。
简单来说就是多继承
注意几个点:
- 多继承用wiht作为关键字
- mixin类中不能实现构造方法,否则不能被其他类进行混合
- dart中每个类除了object外只能有一个基类
- mixin类虽然不能定义构造方法,但是可以用默认构造方法进行实例化
- 如果不想实例化用mixin关键字代替class,同时也不能被继承
- mixin类本身可以继承,只是不能被继承,用on取代extends关键字进行继承