这里我使用的使用的VSCODE软件,非常轻量,推荐。这里基本只会提和java之间的区别。
1. 简单尝试
-
打开 vscode ,安装一下dart插件和CodeRunner插件
- new一个File,我这里是
test1.dart
。这里dart语言文件的后缀名就是dart。 -
写一个最简单的dart语句试试:
右键就可以运行了,这里注意必须CtrlS之后运行,没有类似AS的自动保存功能,直接运行是没有反应的。
运行成功。
2. 语法
Dart在语法方面感觉和JavaScript,和Java非常相似。
-
变量
它是一种功能非常强大的脚本语言,可以不定义变量类型,自动对类型推导。
void main() {
var str = 'hello dart!';
String str1 = 'hello world!';
print(str);
print(str1);
}
-
常量
Dart中常量定义有两个关键词:const
和final
但是这两者还是有区别的,看下下面代码,其中const修饰的常量报错了。
void main() {
const a = "Hello";
final b = "world";
// const time = new DateTime.now(); 报错
final time2 = new DateTime.now();
}
- const是编译时常量
- final拥有const的特性,并且还是运行时常量,final常量是惰性的,只有在第一次运行的时候才会被初始化
获取当前时间的行为无法在编译期间操作,所以const报错了。
-
命名规则
和java一样
-
常用数据类型
- int
- double
- bool
- String
- List
- Map
- Sting类型
和Java不同的是String数据类型添加了新的特性,3个双引号或者3个单引号成对出现,字符串内容可以换行显示。
void main(){
String s = """
hello,
world!
hello,
dart!
......
""";
print(s);
}
结果:
-
运算符
比起JAVA,多出了一个特殊运算符:当b没有被赋值时,??=
的赋值才会生效。
void main(){
// var b;
// b??=2;
// print(b);//2
var b = 7;
b??=2;
print(b);//7
}
-
类型转换
void main(){
var a = "123";
try{
var b = double.parse(a);
print(b);//123.0
print(b.toString());//double -> String 123.0
}catch(err){
print(0);
}
var n = 0/0;
print(n);//NaN
if(n.isNaN){
print("chucuole");
}
}
-
函数
- 函数定义方式
可以不写返回值类型,把int去掉,但是最好加上类型约束,才符合代码规范。
int getNum(int num){
var a = 0;
for(int i= 0;i
- 箭头函数
void main(){
var list = ["a","b","c"];
// list.forEach((v){
// print(v);
// });
// list.forEach((v) => print(v));
list.forEach((v) =>{
print(v)
});
List list1 = [1,3,5,7,8,9];
// var newList = list1.map((v){
// if(v>5){
// return v;
// }
// return "";
// });
var newList = list1.map((v) =>v>5?v:0);
print(newList);//(0, 0, 0, 7, 8, 9)
}
-
闭包
局部变量特点: 1. 不污染全局 2. 会被内存回收
闭包使用:使变量常驻内存 但是不会污染全局
void main(){
fn(){
var a = 1;
return (){
a++;
print(a);
};
}
var b = fn();
b();
b();
b();
}
-
构造函数
- 简化了赋值操作
class Person{
String name;
int age;
Person(this.name,this.age){
}
info(){
print("${name}---${age}");
}
}
void main(){
var p = new Person("haha", 18);
p.info();//haha---18
}
- 比起Java新增了命名构造函数,同时构造函数时不可重载的,算是一个替代吧。
class Person{
String name;
int age;
Person.now(){
print("命名构造函数");
}
Person(this.name,this.age){
}
info(){
print("${name}---${age}");
}
}
void main(){
var p = new Person("haha", 18);
p.info();//haha---18
var p1 = new Person.now();//命名构造函数
}
-
私有属性,私有类,私有方法
其实在前面的学习里我也隐隐感觉到dart可能是个符号狂魔。。但是,好吧,看一下例子。
class Person{
String _name;//私有了
int age;
Person.now(){
print("命名构造函数");
}
Person(this.name,this.age){
}
_info(){//私有了
print("${name}---${age}");
}
}
-
get,set方法
dart中的get,set方法更像把他作为一个类的属性来进行实现。
class Rect{
int mH;
int mW;
set areaH(value){
mH = value;
}
set areaW(value){
mW = value;
}
get area{
return mH*mW;
}
}
void main(){
var r = new Rect();
r.areaH = 5;
r.areaW = 10;
print(r.area);//50
}
定义和调用都不需要括号,是不是特别像static修饰了一样。
-
静态方法
和JAVA一样,用static修饰
-
类的继承
- 和Java一样使用
extends
关键词 - 子类不能继承父类的构造方法
- 子类能复写父类的方法
class Person{
String name ;
int age;
Person.now(this.name,this.age){
}
void getInfo(){
print("${name}---${age}");
}
void work(){
print("${name}在工作...");
}
}
class Worker extends Person{
Worker.now(String name, int age) : super.now(name, age);
@override
void work(){
print("${name}是童工...");
}
}
void main(){
var worker = new Worker.now("xiaoming",15);
worker.work();//xiaoming是童工
}
-
抽象类和接口
- dart中抽象类修饰也是使用
abstract
- 方法不需要abstract修饰,没有方法体就是抽象方法
abstract class A{
b();
}
这里b就是抽象方法。
这里dart的抽象类替代了接口的作用,没有interface这个关键词。你可以理解为dart用抽象类代替了接口。
如果要将抽象类当作接口使用,关键词使用implement
即可。
-
多继承
众所周知,一个类可以继承多个接口,但是不能继承多个抽象类。
dart加入了一个新特性mixins
,可以实现类似多继承的功能,但是他不是继承,也不是接口。
abstract class A{
printA(){
print("A");
}
}
abstract class B{
printB(){
print("B");
}
}
abstract class D{
printD(){
print("D");
}
}
class C with A,B{
}
void main(){
var c = new C();
c.printA();//A
c.printB();//B
}
这里我做了个实验,如果两个被混淆的类有同名方法会发生什么呢?
结论是后一个被混淆的类中的方法会生效,类似方法重载。
对于mixins
类,有几个重要的特性,需要注意。
- 不能拥有构造函数,拥有构造函数的类是无法被混淆的。
- 继承可以和混淆混合使用。
- 如果用 C is A或者 C is B去做类型判断,你会发现返回的都是true
-
泛型
- 定义泛型方法,解决代码复用问题
T getNum(T n){
return n;
}
void main(){
print(getNum(""));
print(getNum("1"));//可以指定类型
}
- 定义泛型类class List
泛型类中一个比较明显的例子就是List
var list = new List();
- 定义泛型接口
- 定义一个泛型接口,约束实现他的子类必须有
getByKey(key)
和setByKey(key,value)
-
setByKey(key,value)
中的value值必须和泛型规定的数据类型一致。
abstract class A{
void setByKey(String key,T value);
getByKey(key);
}
class Test implements A{
@override
getByKey(key) {
return null;
}
@override
void setByKey(String key, T value) {
}
}
-
关键词 async 和 await
- async的作用就是让方法异步。
2.如果使用别的async就要用到await