一 内置的基本类型
1.数值类型:num 【int 和 double】
int x = 1;
double y = 1.1;
// 继承自num的 取整数round ads取绝对值
int z = y.round();
dart:math库 提供了三角函数、指数、对数、平方根等函数
2. bool ture 和 false
3. String 既能用单引号也能用双引号声明
可以使用 ${value} 把一个表达式的值放进字符串。而如果是一个标识符,你可以省略{}
例如:
// 标识符
int a = 10;
var str = 'value $a';
var b = adb;
var strTwo = 'value : ${b.toUpperCase()} ';
4 List、map
// 声明方式一
var arr1 = <String>['one', 'two', 'three'];
// 声明方式二
var arr2 = new List<int>.of([1,2,3]);
// 添加元素
arr2.add(499);
// 遍历打印
arr2.forEach((v) => print('${v}'));
print(arr2 is List<int>); // true
var map1 = <String, String>{'name': 'Tom','sex': 'male',};
var map2 = new Map<String, String>();
map2['name'] = 'Tom';
map2['sex'] = 'male';
map2.forEach((k,v) => print('${k}: ${v}'));
print(map2 is Map<String, String>); // true
二常量定义
- const,表示变量在编译期间即能确定的值;
- final 定义的变量可以在运行时确定值,而一旦确定后就不可再变
区别:
- 在定义const常量时,你必须直接赋一个字面量,而不能是一个变量或者公式;
- 在定义final常量时,如何赋值就无所谓了,但赋值后就不能再改了。
三 函数
函数也是对象,它的类型叫作 Function,函数也可以被定义为变量,甚至可以被定义为参数传递给另一个函数
bool isZero(int number) { //判断整数是否为0
return number == 0;
}
void printInfo(int number,Function check) { //用check函数来判断整数是否为0
print("$number is Zero: ${check(number)}");
}
Function f = isZero;
int x = 10;
int y = 0;
printInfo(x,f); // 输出 10 is Zero: false
printInfo(y,f); // 输出 0 is Zero: true
//函数体只有一行表达式
bool isZero(int number) => number == 0;
void printInfo(int number,Function check) => print("$number is Zero: ${check(number)}");
四 Dart用【可选命名参数】和【可选参数】代替java中的函数重载
4-1 可选命名参数 声明与使用
- 函数定义: 函数定义时,给参数增加{ } 例如:
// 不带默认值的:定义可选命名参数
void method1({bool show, bool hidden}) => print("$show , $hidden");
// 带默认值的:定义可选命名参数时增加默认值
void method2({bool show = true, bool hidden = false}) => print("$show ,$hidden");
- 函数调用:以 paramName: value 的方式指定调用参数,也就是可选命名参数【注意1调用时输入想要用的参数名:value;2未输入的参数并且没有设置默认值的参数默认为null; 3 选定的参数名 与定义的参数名顺序无关】
// 选定使用show参数 value为true
method1(show:true); // 打印:true , null
// 选定使用hidden 参数 value为false
method1(hidden:true);// 打印:null , true
// 测试选定参数名 与 定义顺序无关
method1(hidden:true,show:false);// 打印: false ,true
// 测试带默认值的
method2(show:false); // 打印:false,false
4-2 可选参数
- 函数定义 :定义时给参数增加[ ],则意味着这些参数是可以忽略的,也就是可选参数
//可忽略的参数在函数定义时用[]符号指定
void method3(bool show, [bool hidden]) => print("$show ,$hidden");
//定义可忽略参数时增加默认值
void method4(bool show, [bool hidden = false]) => print("$show ,$hidden");
- 函数调用:需要按函数里 参数的定义顺序 来声明
// 不带默认参数的 只给了第一个参数的值
method3(true);// 输出 true ,null
// 4是 带默认参数的 只给第一个值
method4(true);// 输出 true,false
// 带默认值的 选定了 2个 参数
method4(true,true); // 输出 true ,true
五 类及其构造函数
Dart 中没有 public、protected、private 这些关键字,在声明变量、方法、类时,在前面加上“”即可作为 private 方法使用。如果不加“”,则默认为 public。“_”的限制范围并不是类访问级别的,而是库访问级别
5-1 默认构造函数
一个类,如果没有定义构造函数,那么它将有一个默认的无参构造;
如果这个类有父类,那么默认无参构造,还会调用父类的无参数构造函数。
5-2 普通构造函数
利用dart语法糖:简化参数赋值,不用写构造函数的方法体,记得括号后用分号
class Point {
num x, y;
// Syntactic sugar for setting x and y
// before the constructor body runs.
Point(this.x, this.y);
}
5-3 命名构造函数,【类名.新构造函数名】
class Point {
// 声明变量要初始化 否则报错, 如果不想初始化 使用late
// 将删除诊断信息,但如果在访问变量之前未为其分配值,则会导致在运行时抛出异常
late num x, y;
// 普通构造函数
Point(this.x, this.y);
// 命名构造函数
Point.instance() {
x = 0;
y = 0;
}
}
使用:
var point = Point.instance();
point.x = 100;
// 输出:改变后的值为:100
print("改变后的值为:${point.x.toString()}");
注意:命名构造函数不可继承,如果子类想要有 和父类一样的命名构造函数,那就写个同名的(通常也会在子类的命名构造函数里,调用父类的同名命名构造函数)
5-4 初始化列表【构造函数名的冒号后面,{ 前面的部分】
初始化列表的执行顺序,在整个构造函数的最前面,它除了可以调用父类的构造函数,还可以在构造函数方法体之前,初始化一些成员变量。
情景一:初始化列表,调用父类构造函数
class Person {
String firstName;
Person.fromJson(Map data) {
print('in Person');
}
}
class Man extends Person {
// Person does not have a default constructor;
// you must call super.fromJson(data).
// 初始化列表 调用父类的无参构造
Man.fromJson(Map data) : super.fromJson(data) {
print('in Man');
}
}
main() {
var man = new Man.fromJson({});
// 打印:
// in Person
// in Man
}
情景二:初始化列表,初始化成员变量
class Point {
num x, y, z;
// 普通构造 : 初始化列表中初始化变量z
Point(this.x, this.y) : z = 0; // 初始化变量z
// 命名构造函数: 初始化列表中 重定向构造函数
Point.bottom(num x) : this(x, 0);
void printInfo() => print('($x,$y,$z)');
}
var p = Point.bottom(100);
p.printInfo(); // 输出(100,0,0)
注意:初始化那些final修饰的成员变量时,初始化列表很有用,因为在方法体中,不能给final修饰的成员变量赋值,因为在执行方法体的时候,final修饰的成员变量已经不能变了
import 'dart:math';
class Point {
final num x;
final num y;
final num distanceFromOrigin;
// 在初始化列表 中 初始化 final修饰的变量
Point(x, y): x = x,y = y,distanceFromOrigin = sqrt(x * x + y* y);
}
main() {
var p = new Point(2, 3);
print(p.distanceFromOrigin);
}
5-5 常量构造函数
声明: 定义一个常量构造函数,并且确保所有的成员变量都是final的。
作用: 一个类,创建的对象永远不会改变,你可以在编译期就创建这个常量实例
class ImmutablePoint {
static final ImmutablePoint origin = const ImmutablePoint(0, 0);
final num x, y;
const ImmutablePoint(this.x, this.y);
}
5-6 工厂构造函数
场景:类似于单例,只需要一个实例,不需要每次都创建新的类实例
注意:
- 工厂构造函数不需要每次构建新的实例,且不会自动生成实例,而是通过代码来决定返回的实例对象;
- 工厂构造函数类似于 static 静态成员,无法访问 this 指针;
- 一般需要依赖其他类型构造函数;
- 工厂构造函数还可以实现单例;
class Logger {
final String name;
bool mute = false;
static final Map<String, Logger> _cache = <String, Logger>{};
//分情况返回实例
factory Logger(String name) {
if (_cache.containsKey(name)) {
return _cache[name] as Logger;
} else {
final logger = Logger._internal(name);
_cache[name] = logger;
return logger;
}
}
// 命名构造
Logger._internal(this.name);
void log(String msg) {
if (!mute) print(msg);
}
}
实现单例:
class Singleton {
static final Singleton _singleton = Singleton._internal();
factory Singleton() => _singleton;
Singleton._internal();
}
六 复用 【1继承extends2实现implements3 混入with】
注:
- 在dart中 一个类可以被继承或接口实现
- 在dart中 也是单继承 多实现的
定义一父类:
class Parent {
// 定义2个变量
num x = 0, y = 0;
// 声明一个打印的方法
void printInfo() => print('($x,$y)');
}
6-1 继承类【单继承】
继承,子类会自动获取父类的成员变量和方法实现,子类可以根据需要覆写变量、构造函数、父类方法;
注:
- 子类中构造函数会默认调用父类中无参构造函数(一般为主构造函数)。
- 若父类中没有默认无参的构造函数,则需要显式调用父类的构造函数(可以是命名构造函数也可以主构造函数或其他), 并且在初始化列表的尾部显式调用父类中构造函数, 也即是类构造函数 :后面列表的尾部。
//SonOne 继承自Parent
class SonOne extends Parent {
// 子类新增变量
num z = 0;
// 子类选择性重写单个方法
@override
void printInfo() => print('($x,$y,$z)');
}
6-2 实现接口【多实现】
接口实现,子类需要重新实现成员变量,以及方法的声明和初始化,否则编译器会报错
//SonTwo 是对 Parent 的接口实现
class SonTwo implements Parent {
// 成员变量需要重新声明
@override
num x = 0;
@override
num y = 0;
// 成员函数需要重新声明实现
@override
void printInfo() => print('($x,$y)');
}