之后使用的dart都是2.16.2
main函数
hello world
void main(List<String> args) {
print("Hello world!!!");
}
main
函数是入口,语句结束要加;
声明变量
明确的声明
类型
+变量名
String name = "Steven";
类型推导
关键字var
同swift里的var
,
final
同swift里的let
,
const
同oc里的const
上述关键字一旦确认类型不可改变,
dynamic
任意类型,确认类型后还可以更改类型,调用方法时,编译不会报错,存在隐患
Object
任意类型,确认类型后还可以更改类型,调用方法时,编译会报错
数据类型
int
,num
,double
,bool
其中String
的使用同Python,进行拼接则使用${}
,如果只是变量,则可省略{}
String->num
int.parse(变量)
double.parse(变量)
str.isEmpty
是否是空字符串
num.isNaN
是否为空num
num->String
变量.toString()
集合
list
同数组,set
同集合,map
同字典
枚举
关键词enum
,使用固定的值,类型安全
void main(List<String> args) {
final s = sex.man;
switch (s) {
case sex.man:
print("man");
break;
case sex.woman:
print("woman");
break;
}
print(sex.values);
print(sex.man.index);
}
enum sex { man, woman }
函数
返回类型
(可省略,但不推荐) + 函数名
+ (必选参数
+ [位置可选参数
]或{命名可选参数
}) { 函数体
}
eg:
void sayHello1(String name, [int age = 10]) {
print("$name : $age");
}
void sayHello2(String name, {int age = 12}) {
print("$name : $age");
}
函数作为参数
使用Function
修饰,但不建议,建议直接写函数表达式
eg:
void main(List<String> args) {
//匿名函数
test((a, b) {
print(a + b);
return a + b;
});
}
typedef Calculate = int Function(int a, int b);
void test(Calculate cal) {
var res = cal(2, 3);
print(res);
}
函数作为返回值
eg:
void main(List<String> args) {
//d1是Calculate类型的函数,需要传入a,b两个参数
var d1 = demo();
print(d1(3, 5));
}
typedef Calculate = int Function(int a, int b);
//返回类型Calculate,返回了一个匿名函数
Calculate demo() {
return ((a, b) {
return a * b;
});
}
箭头函数
函数体只有一行代码
() => {print("这是箭头函数")};
{}可以省略
匿名函数
无函数名 (参数
) { 函数体
},参见上面注释
特殊运算符
赋值运算符
??=
当赋值的变量不为空时不赋值,当变量为空时才执行
??
同Swift,符号前面的值不为空时使用前面的值,为空时使用后面的值
级联运算符
..
对一个对象的操作可以通过级联运算符连接,语句结束加;
即可
循环
for
,for in
同oc,switf
类的构造函数
常规的都可以,也可以通过KVC模式构造
eg:
void main(List<String> args) {
var cat = Animal.fromMap({"name": "kitty", "age": 2, "male": true});
//toString()可以省略
print(cat.toString());
var dog1 = Animal("dog", 12);
var dog2 = Animal("dog2", 15, male: true);
print(dog1);
print(dog2);
}
class Animal {
String? name;
int? age;
bool? male;
// 语法糖 初始化列表
Animal(this.name, this.age, {male}) : this.male = male ?? false;
Animal.fromMap(Map<String, dynamic> map, {String}) {
this.name = map["name"];
this.age = map["age"];
this.male = map["male"];
}
@override
String toString() {
return "name:$name,age:$age,male:$male";
}
}
重定向构造函数
关键字_internal
void main(List<String> args) {
var s = Student("Bob");
print(s.age);
}
class Student {
String name;
int age;
Student(String name) : this._internal(name, 20);
Student._internal(this.name, this.age);
}
常量构造函数
void main(List<String> args) {
const s1 = Student("name");
const s2 = Student("name");
//对比得出s1与s2指向同一块内存,是一个对象
print(identical(s1, s2));
}
class Student {
final String name;
const Student(this.name);
}
工厂构造函数
区别:普通的构造函数会返回一个创建的对象,工厂构造函数可以手动返回一个对象。
void main(List<String> args) {
final s1 = Student.withName("bob");
final s2 = Student.withName("bob");
final s3 = Student.withAge("20");
final s4 = Student.withAge("20");
//对比得出s1与s2相等
print(identical(s1, s2));
//对比得出s3与s4相等
print(identical(s3, s4));
}
class Student {
String name;
String age;
static final Map<String, Student> _nameCache = <String, Student>{};
static final Map<String, Student> _ageCache = <String, Student>{};
factory Student.withName(String name) {
//putIfAbsent.如果存在[key],则会返回它的值。如果不存在,就会调用后面的函数,生成新值,然后插入,并返回该值。
return _nameCache.putIfAbsent(name, () => Student(name, "10"));
}
factory Student.withAge(String age) {
return _ageCache.putIfAbsent(age, () => Student("name", age));
}
Student(this.name, this.age);
}
setter和getter
void main(List<String> args) {
var c = Cat();
c.setName = "cat";
print(c.getName);
}
class Cat {
late String name;
set setName(String name) => this.name = name;
/*set setName(String name) {
this.name = name;
}*/
String get getName => this.name;
/*String get getName {
return this.name;
}*/
}
继承
关键字extends
,只支持单继承
void main(List<String> args) {
var c = Cat(20, "kitty");
}
class Animal {
String name;
Animal(this.name);
}
class Cat extends Animal {
int age;
Cat(this.age, String name) : super(name);
}
抽象类
关键字abstract
普通类中的方法必须实现,抽象类中的方法可以不实现;
继承抽象类后,必须实现抽象类的抽象方法
正常情况下抽象类不能实例化(new 类()
),除非加工厂构造函数
external
:将方法的声明和方法的实现分离,通过@patch
实现方法
隐式接口
关键字implements
将一个类作为接口使用时,则实现这个接口的类必须实现这个接口中的所有方法
class Cat {
void running() {}
}
class Dog {
void jumping() {}
}
class Animal implements Cat, Dog {
@override
void running() {
// TODO: implement running
}
@override
void jumping() {
// TODO: implement jumping
}
}
注:继承可以调用super
,实现不可以
继承抽象类和implements区别:
- 如果要福永抽象类里面的方法,并且要用抽象类方法约束子类的话就继承抽象类
- 如果只是把抽象类当标准的话就使用
implements
实现抽象类
mixin混入
关键词mixin
定义,with
混入.优先级:重写 > 混入 > 继承
mixin Cat {
void running() {}
}
mixin Dog {
void jumping() {}
}
class Animal with Cat, Dog {}
- 作为mixins的类只能继承自Object,不能继承其他类
- 作为mixins的类不能有构造函数
- 一个类可以mixins多个mixins类
- Mixins不是继承,也不是接口,是一个全新的特性。
class M extends N with A,B
(一个类M,继承自类N,混入A,B),其中N,A,B有同一个方法,则使用最后一个混入的类B
类属性和类方法
- 使用
static
关键字来实现类级别的变量和函数 - 静态方法不能访问非静态成员,非静态方法可以访问静态成员
void main(List<String> args) {
var c = Cat();
c.name = "mimi";
Cat.kind = "animal";
c.running();
Cat.living();
}
class Cat {
// 成员属性
late String name;
// 类属性
static String? kind;
// 成员方法
void running() {
print("running");
}
// 类方法
static void living() {
print("living");
}
}
extension扩展
extension
扩展名 on
扩展的类 { //扩展内容}
泛型
一般用T
作为关键字,作用:解决类,接口,方法等的复用性(冗余),以及对不特定数据类型的支持(校验)
ok,dart的语法基本就到这里了,异步线程啥的要到后面Flutter
里再学了。