以下内容为自学笔记,若有幸被大神看到,望指正其不准,补充其不足。万分感谢!!!
new
关键字,也可不使用。构造函数名字可以为ClassName
或ClassName.identifier
var list1 = new List();
var list2 = List();
var list3 = List.from(Iterable.empty());
Dart语言的类中的构造函数可分以下形式:
Dart语言中类分为:
Dart语言的类中包含变量和函数
使用 new
关键字和构造函数来创建新的对象
//java中写法
class Point1 {
num x;
num y;
Point1(num x, num y) {
this.x = x;
this.y = y;
}
}
//dart建议写法
class Point2 {
num x;
num y;
Point2(this.x, this.y);
}
main(){
var p1 = new Point1(2, 2);
var p2 = new Point2(2, 2);
}
final
修饰的变量只能初始化一次,但不要求赋的值为编译时常量;而const
要求在声明时就初始化,并且初始化必须为编译时常量。class Test1{
//const修饰成员变量时必须与static同时使用,编译时常量即在编译时就确定了值,
//bool,字符串,数字,list的字面量形式都是编译时常量
static const a = true;
static const int b = 1;
static const c = '字符串';
static const b = [1,2,3];
static const e = b + 2;//其中b也要是const常量
}
final
是惰性初始化,即在运行时第一次使用前才初始化。class Test{
//可以通过以下两种方式初始化,但都是在运行时才会执行
final a ;
final b = 1;//可直接初始化
//可以通过下面方式初始化
Test(this.a){}
Test(a) : this.a= a{}
}
const
可以修饰变量,也可以修饰值,而 final
只用来修饰变量。void test2(){
//const修饰局部变量时,直接使用关键字即可。
//const既可以修饰变量,也可以修饰常量。
const list1 = [1,2,3];
const list2 = const [1,2,3];
// error, 因为new DateTime.now()不是编译时常量
// const list3 = const [new DateTime.now(), 2, 3];
//final只能修饰变量
final list6 = [1, 2, 3];
// final list7 = final [1, 2, 3]; //error
final list8 = const [1, 2, 3];
//const无论修饰变量还是值,后边都必须接编译时常量
var x1 = 5;
// const list4 = const[x1]; //error,x1不是const
const x2 = 5;
const list5 = const[x2];
// error, 因为new DateTime.now()不是const
// final list9 = const [new DateTime.now(), 2, 3];
}
总结:const 修饰值的时候,要求值必需是常量或由常量组成。var、final等在左边定义变量时,并不关心右边是不是常量。但如果右边用了const,那么不管左边是什么要求,右边都必需是常量。
const
替代 new
即可:const
构造函数,类的所有成员变量都要为 final
或const
修饰的。new
调用const
构造函数,但这样就不能使用const
声明变量了。class Point2 {
final num x;
final num y;
static const num z = 9;
const Point2(this.x, this.y);
}
main(){
var p1 = const Point2(2, 2);//ok
const p2 = const Point2(2, 2);//ok
// const p3 = new Point2(2,2);//error
final p4 = const Point2(2,2);//ok
final p5 = new Point2(2,2);//ok
assert(identical(p1, p2));//判断是否是同一个实例对象 true
assert(identical(p1, p4));//判断是否是同一个实例对象 true
assert(identical(p1, p5));//判断是否是同一个实例对象 false
}
ClassName.identifier
,类名.标识符(即方法名)。class Point {
num x;
num y;
//常规的构造函数
Point(this.x, this.y);
// 此处是命名构造函数
Point.fromJson(Map json) {
x = json['x'];
y = json['y'];
}
}
initializer list
(初始化参数列表),则初始化参数列表在超类构造函数执行之前执行。:super
调用。class Person {
String firstName;
Person.fromJson(Map data) {
print('in Person');
}
}
class Employee extends Person {
// Person父类没有默认构造函数;
// 这里必须调用父类的构造函数 super.fromJson(data).
Employee.fromJson(Map data) : super.fromJson(data) {
print('in Employee');
}
}
main() {
var emp = new Employee.fromJson({});
// 此处打印结果:
// in Person 此处先执行父类的构造函数
// in Employee 然后执行子类的构造函数
}
注:调用超类构造函数的参数无法访问
this
。例如,参数可以为静态函数但是不能是实例函数。
super()
,需要把它放到最后。import 'dart:math';
class Point {
final num x;
final num y;
final num distanceFromOrigin;
// Initializer list sets instance variables before
// the constructor body runs.
Point(x, y)
: x = x,
y = y,
distanceFromOrigin = sqrt(x * x + y * y);
}
main() {
var p = new Point(2, 3);
print(p.distanceFromOrigin);
}
//3.605551275463989
**警告:**初始化表达式等号右边的部分不能访问
this
。
: this.xxx
调用其他构造函数。{}
。class Point {
num x;
num y;
// The main constructor for this class.
Point(this.x, this.y);
// Delegates to the main constructor.
Point.alongXAxis(num x) : this(x, 0);
}
factory
来定义这个构造函数。class A{
String name;
//注意: 工厂构造函数无法访问 this。所以这儿要静态的
static A _cache;
//工厂构造函数的关键字为factory
factory A([String name = 'A']){
if(A._cache == null){
A._cache=new A._newObject(name);
}
return A._cache;
}
//需要一个命名构造函数用来生产实例
A._newObject(this.name);
}
void goFactory(){
A a = new A('HelloWorld');
print(a.name);
A b = new A('HelloDart');
print(b.name);
print(a == b);
}
//打印结果
HelloWorld
HelloWorld
true
在Dart语言中,每个实例变量都隐含的具有一个get
方法,如果变量不是fianl
的则还有个set
方法。
在Dart中声明变量有两种方法,但调用方法一样。
var temp ;
,此时会有默认的get
和set
方法与之对应; num a;
get
和set
方法声明。 num get c {
//自定义实现,不影响调用处
return a + b;
}
set c(num value) {
//自定义实现,不影响调用处
a = value + b;
}
** 注:**两种方式不可同时使用,否则会报:
Error: 'c' is already declared in this scope.
错误。
在使用过程中,当执行var temp = 实例.变量;
这句时,就调用了变量的get
方法;当执行实例.变量 = 5;
时,就调用了变量的set
方法。
基于第3点,此时修改变量的set和get方法的内部实现时,调用变量的代码不需要修改。
class GetAndSet {
num a;
num b;
GetAndSet(this.a, this.b);
//声明变量c 的get方法
num get c {
print('get c');
return a + b;
}
//声明变量c的set方法
set c(num value) {
print('set c');
a = value + b;
}
}
main() {
var i = new GetAndSet(4, 7); //此时 a = 4 ,b = 7;
i.c = 4;//此时调用了set c a = 4 + b = 11 ;b = 7 ,c = 18;
var k = i.c;//此时调用了get c a = 11 ,b = 7 ,c = a + b = 18 ,k = c =18
print('i.a = ${i.a},i.b = ${i.b},i.c = ${i.c},k = $k');
}
//打印结果
//set c
//get c
//get c 这里是print中i.c打印的
//i.a = 11,i.b = 7,i.c = 18,k = 18
abstract
修饰类。;
代替函数体也就是没有大括号{}
。run();
abstract class Car {
run();
space() {
print('普通方法!');
}
}
class Bus extends Car {
int width = 4;
Bus(this.width);
//必须复写抽象方法,也可空实现
@override
run() {
print('Bus 起飞跑');
}
}
implements
实现一个或多个接口,并要实现接口中所有成员变量和函数。abstract class Car {
run();
space() {
print('car的普通方法!');
}
}
class Bus extends Car {
int width = 4;
Bus(this.width);
//必须复写抽象方法,也可空实现
@override
run() {
print('Bus 起飞跑');
}
}
class C implements Bus {
//成员变量也要实现
@override
int width;
//从新实现 接口重写父类的抽象方法
@override
run() {
print('C 的 run方法!');
}
//从新实现 接口继承父类的方法
@override
space() {
print('C 的space方法!');
}
}
main() {
var c = new C();
c.run();
c.space();
}
//打印结果 接口实现的方法不会有父类的实现
C 的 run方法!
C 的space方法!
mixin是一种在多类继承中,重用一个类代码的方法。
使用关键字with
后面接一个或多个类。
mixin类不可以含有构造函数。
mixin与接口不同都是,传统接口不包含实现部分,而mixin中是包含实现部分的。
mixin与传统的继承和接口混合使用的区别:
class S {
a() {
print("S.a");
}
b() {
print("S.b");
}
c() {
print("S.c ");
}
}
class A {
a() {
print("A.a");
}
b() {
print("A.b");
}
}
class B {
a() {
print("B.a");
}
//如果不注释此方法,则打印结果都为 B.a B.b B.c
// b() {
// print("B.b");
// }
c() {
print("B.c ");
}
}
class T extends B implements A,S{
@override
b() {
print("T.b");
}
}
main() {
T t = new T();
t.a();
t.b();
t.c();
assert(t is S);//ture
}
//打印结果
B.a
T.b
B.c
class S {
a() {
print("S.a");
}
b() {
print("S.b");
}
c() {
print("S.c ");
}
}
class A {
a() {
print("A.a");
}
b() {
print("A.b");
}
}
class B {
a() {
print("B.a");
}
b() {
print("B.b");
}
c() {
print("B.c ");
}
}
class T extends B with A,S{
}
// class T = B with A, S; 可以写成这样
main() {
T t = new T();
t.a();
t.b();
t.c();
assert(t is S);//ture
}
//打印结果
S.a
S.b
S.c
//如果注释了S中的b方法,则打印结果为
S.a
A.b
S.c
注意: 从 Dart 1.13 开始, 这两个限制在 Dart VM 上 没有那么严格了:
- Mixins 可以继承其他类,不再限制为继承 Object
- Mixins 可以调用
super()
。
总结:
mixin机制可以为类增加新的功能,使用with 将前后类中的相同方法通过优先级挑选出来与各自的不同方法,从新综合到一个新类中。如下:
class S {
a() {
print("S.a");
}
}
class A {
a() {
print("A.a");
}
b() {
print("A.b");
}
}
class B {
a() {
print("B.a");
}
b() {
print("B.b");
}
c() {
print("B.c ");
}
}
// class T = B with A, S;与下列方式一样
class T extends B with A,S{}
//此时的T类就相当于是
class T{
a() {
print("S.a");
}
b() {
print("A.b");
}
c() {
print("B.c ");
}
}
main() {
T t = new T();
t.a();
t.b();
t.c();
assert(t is S);//ture
}
//打印结果
S.a
A.b
B.c