变量
-
1、使用var 声明变量,可以赋予不同类型的值,var可以在运行中推导出变量的类型,确定了便不能更改类型
-
2、使用Object,这个关键字大家应该都很熟悉,Java中的所有对象的父类就是Object,Object和var不同的点是即使赋了初始值,也可以指定别的类型,例如int,String,Num等。
-
3、dynamic 和Object非常类似,唯一的区别就是如果你调用一个本身不存在的方法,Object会在编译器就直接报错,而dynamic则会在运行的时候才会抛出异常
//var定义变量 var name = 3; name = "Bob"; // 编译报错:A value of type 'String'can't be assigned to a variable of type 'int'. //Object定义变量 Object a = 'blob'; a = 123; a = []; // 动态定义变量 dynamic _name = 'Bob'; _name = 3; // object和dynamic的区别 Object testa = "asd"; // testa.substring(1);//编译失败:The method 'substring' isn't defined for the type 'Object'. //正确1强转 :print("Object>>>>"+(testa as String).substring(1)); dynamic testdy = "restdy"; print(testdy.substring(1));//编译通过
常量
- 常量在dart中可以用final和const来修饰
- final包含了const的功能,区别在于
1、final可以接受运行时的数据,const则只能接受编译时的数据
2、const 必须给一个明确的编译常量值(即编译期间就确定的值),final 可以一开始不赋值。
3、final 是惰性初始化,运行时第一次使用前才进行初始化
4、const在修饰类中变量时,则必须加上static变量
//-----第一点:-----
final time = DateTime.now();
// const time2 = DateTime.now();//编译报错:Const variables must be initialized with a constant value.
//-----第二点:-----
//正确
const atest = 1;
const btest = atest > 1 ? 2 : 1;
//错误
var atest2 = 1;
//下面这句报错:Const variables must be initialized with a constant value
// const btest2 = atest2 > 1 ? 2 : 1;
//如果字符串是const 声明的编译时常量,编译时常量 (null、数字、字符串、布尔) 才可以作为该字符串字面量的插值表达式。
// 这些在 const 声明的字符串常量中能用
const aConstNum = 0;
const aConstBool = true;
const aConstString = 'a constant string';
// 这些在 const 字符串中不能用,用 var 声明的才有用
var aNum = 0;
var aBool = true;
var aString = 'a string';
const aConstList = [1, 2, 3];
const validConstString = '$aConstNum $aConstBool $aConstString';
//编译出错:In constant expressions, operands of this operator
// must be of type 'bool', 'num', 'String' or 'null'.
// const invalidConstString = '$aNum $aBool $aString';
var validConstString2 = '$aNum $aBool $aString $aConstList';
print(validConstString2);
//--第三点-----
// const a; //编译报错: The constant 'a' must be initialized.
final testfinal;
testfinal = "3";
//第四点
class Test{
const String name="jack";//报错提示:尝试将字段声明为
//最终字段,或添加关键字“静态”。
void getString(){
const String name2="jack";
}
}
5、final 只可用来修饰变量, const 关键字不仅仅用来定义常量,还可以用来创建常量值,该常量值可以赋予给任何变量。也可以将构造函数声明为 const,这种类型的构造函数创建的对象是不可改变的。
6、const 修饰对象时,要在构造方法加const
//5、const修饰的数组列表不能被修改
var foo = const [1,2,3];
// foo[0] = 3;//报错:Cannot modify an unmodifiable list
// print("foo:{$foo}");
//final定义的数组列表可以被修改
final bar = [1,3,4];
bar[0] = 9;
print("bar:${bar}");//正确
//一样不能被修改
final barconst = const [];
// barconst[0] = 9;//报错:Cannot modify an unmodifiable list
const baz = []; // 相当于`const []`
baz.add("value");
print(baz);//报错:Cannot add to an unmodifiable list
//const 修饰对象
//const 修饰对象时,要在构造方法加const
//否则会报:Cannot invoke a non-'const' constructor where a const expression is expected.
const p1 = const Person('myname');
const p2 = Person('myname'); // 右边的const 可以省略
var p3 = const Person("myname");
print("---------${identical(p1, p2)}");// true
print("---------${identical(p1, p3)}");// false
- 关于identical函数(检查两个引用是否指向同一个对象。)
//官方说明
var o = new Object();
var isIdentical = identical(o, new Object()); // false, different objects.
isIdentical = identical(o, o); // true, same object
isIdentical = identical(const Object(), const Object()); // true, const canonicalizes
isIdentical = identical([1], [1]); // false
isIdentical = identical(const [1], const [1]); // true
isIdentical = identical(const [1], const [2]); // false
isIdentical = identical(2, 1 + 1); // true, integers canonicalizes
关键字
- 带有上标1的是上下文关键字,仅在特定位置具有含义。它们是可以在任何地方作为标识符。
- 带有上标2的单词是内置标识符。为了简化将JavaScript代码移植到Dart的任务,这些关键字在大多数地方都是有效的标识符,但它们不能用作类或类型名称,也不能用作导入模块时的前缀。
- 带有上标3的单词是与Dart 1.0发布后添加的异步支持相关的关键字。
part和part of
这个关键字可以把文件分成多个文件,将一个大的lib拆分成多个小的文件
注意part跟part of 要配套使用
- A类
part "B.dart"//指明B是A的一部分
- B类
part of "A.dart"//指明B是属于A的一部分
运算符
//赋值运算符
var a = 1;
int? b;
print(b);//null
b ??= 2; // 如果 b 为空的话就把 2 赋值给 b
print(b);//2
a += 0;
print(a);//1
// 算数运算符
//a=1,b=2
print(a + b);//3
print(a - b);//-1
print(a * b);//2
print(a / b);//0.5 在java中会进行取整运算,在dart中会自动推导成小数
print(a % b); // 取余 1
print(a ~/ b); // 取整 0 ===>和java的取整一样
//以下和java一样
// a++ // 先运算再自增
// a-- //先运算再自减
// --a // 先自减再运算
// ++a // 先自增再运算
print("========关系运算符========");
////a=1,b=2
//关系运算符
print(a == b);//false
print(a >= b);//false
print(a "zhujiang";
String test1(){
return "zhujiang";
}
//可选命名参数
main() {
print(add(a: 1, b: 3));
}
int add({int a = 1, int b = 0}) {
return a + b; // 输出4
}
//可选位置参数
int add2(int a,[int b = 2,int c = 3]) {
return a + b;
}
print(add2(1));//3
print(add2(1,2));//3
print(add2(1,1,3));//2
//必选在可选参数之前
int add2([int b = 2,int c = 3],int a) { // 报错:Expected to find ')'.
return a + b;
}
int add3(int c,{int a = 1, int b = 0}) {// 报错:Expected to find ')'.
return a + b;
}
匿名函数
- 分为有参匿名和无参数匿名
//无参
var printFun = () => print("**无参匿名函数**");
//有参
var printFun2 = (name) => print("**有参匿名函数 $name**");
printFun2("sss");
闭包
- Dart内也有闭包的定义,这和JavaScript相似
Function makeAddFunc(int x) {
return (int y) => x + y;
}
var makeAddFun = makeAddFunc(11);
void main(){
print(makeAddFun(10));//输出21
}
词法作用域
- Dart 的作用域是词法作用域,跟 JavaScript 一样,在写代码的时候就确定了。
void test1(){
var a = 2;
void test2(){
var b = 3;
print(a);
}
}
逻辑控制
// for 循环
for (var i = 0; i 0) {
print(while1);
while1--;
}
print("======do-while======");
// do-while
var i = 5;
do {
print(i);
i--;
} while (i > 0);
// do while 跟 while 的区别是即使不满足条件,do while 循环也会 do 一次;while 循环不会
// 断言——assert
// assert(1 2, '1>2 is wrong');//当表达式为false,抛出异常: '1 > 2': 1>2 is wrong
print("====异常-捕获=====");
// 异常-捕获
try {
// throw Error(); // 输出:No specified type, handles all error Instance of 'Error'
//抛出异常
// throw Exception(); // 输出 this is Unknown exception Exception
// ('this is exception error');
// num i = 3 / 0;
int i = 3~/0; // IntegerDivisionByZeroException
print(i);
} on Exception catch (e) { //1. 需要指定异常类型时使用on
print('this is Unknown exception $e');
rethrow;//3. 要部分处理异常,同时允许它继续抛出异常,请使用rethrow关键字,
// rethrow 会保留原异常的堆栈信息,而throw里面的堆栈信息会重新定位到最近的点
// throw e;//这个堆栈信息打印就会只定位到88行。而rethrow会定位到真正错误的点,所以再次
// 在try-catch里面抛出异常,最好使用rethrow
} catch (e,s) {
print('No specified type, handles all error $e');
print('Stack trace:\n $s');
}finally{
print("finally "); // 一定会执行
}
//补充:如果有finally,finally代码块一定会执行,
//所以finally代码块如果有return ,则会覆盖掉try/catch里面的return,
//这点和java一样
Dart面向对象
类与对象
- 构造函数
- 命名构造函数
- 常量构造函数
- 工厂构造函数
- Getter和Setter
//dart中的构造函数
class Point {
num x;
num y;
Point(this.x, this.y);
// String? name; // Declare instance variable name, initially null.
// int _age = 0;
// 2、命名式构造函数——使用初始化列表===>写法:类名.函数名():命名参数
// Person.origin(String name,int age):this.name = name,this._age = age;
// 命名式构造函数的另一种写法
// Person.origin(String this.name,int this._age);
// 3、常量构造函数
// 使用常量构造函数,要注意两点:一是要确保所有实例变量都是final;
// 二、构造器前面要有const关键字,且不能要有函数载体
final String? name; //
final int _age; //
const Person(this.name, this._age);
// 工厂构造函数
static Person? instance;
factory Person.getInstance(){
if(instance == null){
instance = Person("name", 31);
}
return instance as Person;
}
}
get和set
- 这个的好处是可以监听属性值的变换
class Rect {
int height;
int width;
Rect(this.width, this.height);
// 手动指定 getter 的写法
get area {
return this.height * this.width;
}
// 手动指定 setter 的写法
set h(int value) {
print("当你调用 xx.h 时,会打印这段话,表示你已经被监听到了");
this.height = value;
}
set w(int value) {
this.width = value;
}
}
void main(List args) {
var p = Rect(10, 20);
print(p.area);// getter
p.h = 100;// setter
p.w = 100;
print(p.area);
}
静态成员
Dart泛型
- 作用:把类型延迟到使用的时候指定
show(T a){
print(a);
}
void main(List args) {
show("hello");//"hello"
//example2
var p = My();
p.say(3);//3
}
class My{
say(T a){
print(a);
}
}
相关资料
Dart官网教程
Dart在线编辑器
掘金中的Dart相关文章
掘金中的Dart相关文章2:Dart从入门到放弃
Dart关键字说明
flutter1
flutter2\