1.相关概念
- 任何保存在中的都是一个,并且所有的实例都对应一个类的实例。无论是数字,函数,null都是对象。所有的对象都是继承Object。
tips:这与Swift是不同的,Swift是有值类型的。 - 可以用var是声明类型,编译器会自动判断类型,一旦编译器判断出类型,那么该变量的类型就不能再去可变。(var声明时未赋值,使用Object声明,使用dynamic声明这三种是可以改变类型的)。
tips:这与PHP是不同的,PHP是可以任意改变类型的。 - Dart中没有权限修饰符( “public” , “protected” 和 “private”),如果想让变量或者方法私有,变量名或者方法名前面加个_,并且只是对于包是私有的。
2.变量
- 变量其实存储的是引用
- 默认值:因为dart中所有的变量都是对象,所以默认值都是null,即使声明类型但是没有赋值的变量也是null。int count中的count类型的值就是null。
tips:Swift中变量要么可选,可选就是没值。要么有值就是一定要手动赋值。OC中值类型像int默认是0。 - final const:如果一个变量的值不会改变,那么就用final或者const去声明(如果是var声明,final或const直接替代var。如果具体类型声明,final或const写在类型前面),const可以被子类继承。
const修饰值。 您可以在创建集合时使用它,例如const [1,2,3] ,以及构造对象(代替new),比如const Point(2,3)。这里,const意味着对象的整个深度状态可以在编译时完全确定,并且对象将被冻结并完全不可变。
tips:final修饰的必须要初始化!!!。final修饰的变量,其引用不可变,但是引用指向的值是可变的。具体看下面的代码:
final list0 = [1,2,3];
list0[0] = 4;
var list1 = const [1,2,3];
list1[0] = 4;//这样会报错
对于任何给定的const值,无论const表达式被计算多少次,都将创建并重用单个const对象:
getConst() => const [1, 2];
main() {
var a = getConst();
var b = getConst();
print(a === b); // true
}
const 关键字不只是用于声明常量,还可以用它来创建常量值(注意是值);以及声明创建常量值的构造函数。任何变量都可以具有常量值。
var foo = const [];
foo = [1, 2, 3]; // 第一次赋值;
foo = [2, 3, 4]; // 错误: const变量不能再次赋值;
const修饰构造函数就是常量构造函数,常量构造函数必须用于成员变量都是final的类!构建常量实例时必须调用常量构造函数。如果实例化时不加const修饰符,即使调用的是常量构造函数,实例化的对象也不是常量实例
class Point {
final int x;
final int y;
const Point(this.x, this.y);
}
void main() {
//条件:如果Point(this.x, this.y)构造函数没有被const修饰
const point = Point(1, 2); // 报错 const对象一定要调用常量构造方法(没有常量构造方法)
var point = const Point(1, 2); // 报错 const对象一定要调用常量构造方法(没有常量构造方法)
//条件:有常量构造函数
var point = Point(1, 2);//point可以被重新赋值
var point1 = const Point(1, 2); // point1可以被重新赋值
const point2 = Point(1, 2); // point2不可以被重新赋值(默认调用常量构造方法)
const point3 = const Point(1, 2); // point3不可以被重新赋值
}
3.操作符
- 级联操作符..
querySelector('#confirm') // 获取html元素对象
..text = 'Confirm' // 访问成员
..classes.add('important') // 添加样式
..onClick.listen((e) => window.alert('Confirmed!')); // 监听事件
var button = querySelector('#confirm');
button.text = 'Confirm';
button.classes.add('important');
button.onClick.listen((e) => window.alert('Confirmed!'));
- 条件的成员访问?. 在不明确对象是否存在的情况下使用 ?. 访问对象的成员(跟Swift的可选类型有点相似,但是不同)
class Test {
num member = 1;
}
void main() {
var test = null;
print(test?.member); // 返回null 不会抛出异常
test = new Test();
print(test?.member); // 返回 1
}
4.内置类型
- numbers
包含int,double。必要的时候int会自动转换成double。 - strings
字符串中可以用${expression} 进行插值或者表达式 - booleans
- lists
var constantList = const [1, 2, 3];
constantList[1] = 1; // 报错
- maps
final constantMap = const {
2: 'helium',
10: 'neon',
18: 'argon',
};
constantMap[2] = 'Helium'; // 报错
- runes(用于在字符串中表示 Unicode 字符)
- symbols(Symbol 字面量是编译时常量,几乎不会用到)
5.函数
- 函数的返回值类型可以省略,但是建议明确声明返回类型。如果函数不返回值,那么程序默认返回null。
- 可选参数:
可选命名参数
//参数列表{}里面的参数是否传值可选,@required修饰的除外
//@required表示调用时必须传该参数 不然报错
//可以设置默认值,没有提供默认就是null
void funcName({bool args1, @required bool args2, bool args3 = false}) {...}
可选位置参数
//[]里面的就是可选位置参数 也是是否传值可选 但是一旦传值必须按位置传值!
void funcName(String args1,[bool args2, bool args3]) {...}
6.异常
- 直接 throw 任意对象,方法不必像java一样声明它们抛出的异常
throw FormatException('Expected at least 1 section');
throw 'Out of llamas!';
- try
try {
breedMoreLlamas();
} on OutOfLlamasException { //使用 on 来指定异常类型
// 一个特殊的异常
buyMoreLlamas();
} on Exception catch (e) { //使用catch来捕获异常对象,最终的捕获是靠catch,on只是条件附加
// 其他任何异常
print('Unknown exception: $e');
} catch (e) {
// 没有指定的类型,处理所有异常
print('Something really unknown: $e');
} finally {
//无论是否有异常 都会执行这一句
}
- 自定义异常可以通过实现Exception接口
7.类
构造函数
子类不会继承父类的构造函数。
- 构造函数种类:
普通构造函数:ClassName(...)
命名构造函数:ClassName.identifier(...)
常量构造函数:const ClassName(...)
工厂构造函数:factory ClassName(...) - 默认构造函数:
如果一个类没有提供构造函数,那么dart默认会提供一个无参的构造函数。默认构造函数会默认调用父类的"无参"构造函数。 - 命名构造函数:
不能被继承,可以有多个。类似于OC的类实例化方法。如果希望使用父类中定义的命名构造函数创建子类, 就必须在子类中实现该构造函数。命名构造函数即使方法体为空也能自动创建类的实例。 - 常量构造函数:
如果该类生成的对象是固定不变的, 那么就可以把这些对象定义为编译时常量。 为此,需要定义一个 const 构造函数, 并且声明所有实例变量为 final。
常量构造函数保证了创建的变量是唯一的实例。
var a = const ImmutablePoint(1, 1);
var b = const ImmutablePoint(1, 1);
assert(identical(a, b)); // 它们是同一个实例。
//注意这俩的区别
var c = const ImmutablePoint(1, 1); // 创建一个常量对象
var d = ImmutablePoint(1, 1); // 创建一个非常量对象
assert(!identical(a, b)); // 两者不是同一个实例!
- 工厂构造函数:
当执行构造函数并不总是创建这个类的一个新实例时,则使用 factory 关键字。 例如,一个工厂构造函数可能会返回一个 cache 中的实例, 或者可能返回一个子类的实例。工厂构造函数无法访问this。调用的话跟普通构造函数一样。但是:工厂构造函数不会主动创建类的实例,只能在工厂构造函数中返回一个实例!
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);
}
}
实例变量
- 非final的实例变量都会隐式生成getter setter方法。final的实例变量只隐式生成getter方法。
- get set方法
class People {
String _name;
set pName(String value) {
_name = value;
}
String get pName {
return 'people is ${_name}';
}
}
抽象类
abstract修饰,不能被实例化。如果希望抽象类能够被实例化,那么可以通过定义一个 工厂构造函数来实现。
抽象方法:不实现方法体就是抽象方法,不需要用abstract修饰。
接口
dart中每个类都能作为接口被其他类所实现,使用implements关键字。接口包含类里的所有成员变量,以及定义的方法(不包含构造方法)。
注意: implements A表明类必须实现A中的属性以及方法(并不继承接口中的属性值或者方法体,只是规定类中必须实现接口的要求的属性或者方法)。
mixin(目前只是简单介绍,后续实际开发中更新)
继承,实现,混入是可以同时存在的,extends在前,mixins在中间,implements最后。
mixin一般用with。
"with多个类的话",如果多个类中有同样的方法,那么后面的方法会覆盖前面的方法。
子类中如果有跟父类、接口、mixin相同的方法,一定执行的是子类的方法。
如果子类的mixin跟父类以及接口有相同的方法,那么执行的一定是mixin的方法。前提是子类中没有与之相同的方法(原理就是mixin会覆盖extends相同方法,而implements只是要求实现方法,并不继承方法体。mixin恰好实现了这个方法)。
main(List<String> args) {
var tool = Tool();
tool.say();
print(tool.name);
}
class Tool with A, B {}
class A {
var name = "A";
say() {
print("A");
}
}
class B {
var name = "B";
say() {
print("B");
}
}
网友评论