文章目录
前言
每个语言都有控制流语句就不写测试代码了。
Win11代码测试方式:
你要把电脑中的flutter和dart环境都安装上,然后在Android Studio中新建一个Dart项目或Flutter项目即可测试
没有安装的可以参考本文:https://blog.csdn.net/qq_41872247/article/details/139375636
新建一个dart文件,void main就可以在编译器运行。
1. 类型声明
dart支持以下几种类型声明方式:
- 和Java一模一样的强类型声明。
- var开头直接声明一个对象,他会自己做类型推断(同kotlin或者js)。
- dynamic声明,可变类型对象,就是可以动态赋值为不同的类型,编译时对于dynamic声明的对象不做类型检查。
- Object声明,同dynamic,但是编译时会将类型确定为Object,除了Object自带的方法以外无法通过编译(其实就是Java的Object)。
void main() {
Obj obj = new Obj();
obj.func();
var obj1 = new Obj();
obj1.func();
var obj2;
obj2 = new Obj1();
obj2.funcc();
dynamic obj3 = Obj();
obj3.func();
obj3 = Obj1();
//obj3.func(); 可以编译,但是无法运行
obj3.funcc();
Object obj4 = 3;
//obj4 = obj4 + 4; 通不过编译
obj4 = "asdqwd";
//obj4 = obj4.subString(0, 3) 通不过编译
obj4 = [3, 6, 9];
print(obj4);
}
class Obj {
void func() {
print("test");
}
}
class Obj1 {
void funcc() {
print("test1");
}
}
2. 数据类型
2.1 基本数据类型
在java里面,int,double这种基本数据类型是没有自带方法的,只有封装的Int和Double对象才有对应的方法,dart省略了这一步,直接就可以int,double,boolean进行一些方法处理。
Dart取消了使用率不高的byte,short,long这三个基本数据类型。
void main() {
//int和double都继承num.dart这个类,里面就有相关的api。
int a = -4;
print(a);
print(a.toDouble());
print(a.abs());
//long a = 1; 无法过编译
//short a = 1; 无法过编译
//byte a = 1; 无法过编译
}
不过,虽然自动封装了对应的API,但是仍然是基础数据类型,是值传递。
void main() {
int a = -4;
Obj o = new Obj();
test(a);
test(o.a);
print(a); // -4
print(o.a); // -4
test2(o);
print(o.a); // -1
}
void test(int num) {
num = num + 3;
}
void test2(Obj obj) {
obj.a = obj.a + 3;
}
class Obj {
int a = -4;
}
常量
Dart同时使用const关键字和final关键字,且如果是基础数据类型的话就不需要声明类型,他会自行做类型推断。
const关键字声明的是常量
final声明的是可以定义一次的变量
const a = 1; // 声明时不需要写var,也不需要写int
//const Obj o = Obj(); 编译报错
final a1 = 1;
final Obj o1 = Obj();
late final a2; // 后续再赋值
void main() {
//print(a2); 运行报错
//a1 = 3; 编译报错
a2 = 3;
}
class Obj {
int a = 4;
}
2.2 String
- String可以使用单引号,也可以使用双引号,当使用双引号的String时,内部的单引号就不需要转义可以直接使用,反之也一样。
- String支持用取地址符(&)拼装变量,和kotlin的一样
- 多个常量String拼接的时候不需要+,直接拼就行
- String前面加上字符r,会自动忽略字符串的所有转义符。
void main() {
String str0 = "外侧是双引号,内侧'单引号'不用转义符";
String str1 = '外侧是单引号,内侧"双引号"不用转义符';
String str2 = "外侧是双引号,内侧\"双引号\"需要用转义符";
String str3 = "外侧是单引号,内侧\'单引号\'需要用转义符";
String str4 = str0 + str1 + " $str0";
String str5 = 'awdqwd'
'qwdqwd'
'qwdqwdqwd'
'qwdqwdqwd';
String str6 = "adqwd""qwdqwdqwd";
String str7 = "qww\nqwe";
String str8 = r"qww\nwww";
}
2.3 集合
- List和数组融合,可以直接用[]创建,不需要new List(语法优化)。
- List内部没有类型检测,可以任意放东西进去。
- Map采用字典的方式,可以直接用{}创建,可以用[]直接修改map。(语法优化)
- 集合创建的时候可以用上const关键字,此时里面的数据类型只能是const类型,也就是常量。
void main() {
List list = [];
list.add("qqq");
list.add(1);
list.add(new Obj());
Map map = {'qq': 'xiaobing', 'qqq':3, 'qqq1': new Obj()};
map['12'] = 3;
print(map);
var a = new Obj();
Map map1 = const {'qq': 'xiaobing', 'qqq':3, 'qqq1': a}; // a编译不通过
}
class Obj{}
2.4 unicode
- 可以输入String中不支持的一些字符
void main() {
Runes runes = new Runes('\u{1f661} \u6211');
print(String.fromCharCodes(runes));
}
3. Dart函数特征
Dart的函数语法模式和Java类似,也是一样的返回类型在前,参数列表中也是类型在前的写法。
void main() {
print(test("a", "b")); // ab
}
String test(String a, String b) {
return a + b;
}
同时Dart语法中的参数是kotlin同款的空类型判断的,在参数类型后面加上?表示该参数可以传空值,不加就不能传了。
void main() {
print(test1("a", null));
}
// ?表示b这个参数可以传空
String? test1(String a, String? b) {
if(b != null) {
return a+b;
}
return null; // 返回类型加上?后可以返回空
}
3.1 可变参数列表和默认入参
Dart不支持Java模式的函数重载,即函数名相同,参数列表或返回类型不同的多个函数同时存在,但是对应的是,Dart的函数支持可变参数列表,可以直接自定义必须要传入的参数和可以传也可以不传的参数,用花括号{}。
void main() {
print(test2("a", b: "b", c: null));
}
// 在花括号里面的参数就是可以传也可以不传的,但是加了required关键字的还是必须要传的
String test2(String a, {required String b, required String? c, String d="dddd", String? e}) {
var str = "";
if(c != null) {
str += c;
}
if(e != null) {
str += e;
}
return a + b + d + str;
}
// 同时,作为可变参数,required,?,默认值三个模式中至少要有一个,都没有的话就过不了编译
String test20(String a, {String b}) { //编译过不去
return a;
}
中括号模式:也能用做可变参数列表,但是不支持required关键字
void main() {
print(test3("a"));
}
String test3(String a, [String b="bb", String? c="ccc", String? d]) {
return a;
}
// 同上,都没有过不了编译
String test30(String a, [String b]) {
return a;
}
3.2 匿名函数
和其他语法的万物皆可对象是一个道理,可以单独将一个函数声明成对象,只是具体写法上有不同,用箭头表明。
void main() {
// 单行直接用箭头,返回类型自动推测
var a = (int a, int b) => a + b;
print(a(1, 2));
// 多行用花括号,返回类型自动推测
var b = (int a, int b) {
a = a + 1;
return a + b;
};
print(b(1, 2));
//无返回类型
Function c = () => print("ccc");
//print(c()); // 编译过不去,因为c返回类型是void
c();
}
当然你懂得,函数本身当然也可以作为函数的入参
void main() {
test(() => print("a"), () => print("bb"));
}
void test(Function a, Function b) {
a();
b();
}
3.3 typedef
typedef可以让你将一个特定入参列表的匿名函数作为一个对象的类型,然后再实际的来定义他的具体功能。
typedef实际名称叫函数签名,不好理解的话你可以将其理解成只有一个方法的接口。
void main() {
fun1 f1 = (int a) {
print("我是f1,a=" + a.toString());
};
// 编译过不去,因为fun1是一个只有一个入参的方法
/* fun1 f2 = (int a, int b) {
print("我是f2");
};*/
}
typedef fun1(int a);
typedef fun2(int a, int b);
有了这个typedef后,你在定义函数入参的时候就能更精确入参的类型了。
void main() {
fun1 f1 = (int a) {
print("我是f1,a=" + a.toString());
};
test(f1);
}
typedef fun1(int a);
void test(fun1 f1) {
f1(555);
}
4. Dart面向对象
Dart的类的定义模式和Java基本一样。
4.1 构造函数
首先,Dart为了方便使用Java的程序员使用Dart语法,所以他支持Java的同款构造函数,只是不支持重载构造函数。
void main() {
// 三种构造函数都能用
var userInfo1 = UserInfo1.con2();
userInfo1 = UserInfo1("aa");
userInfo1 = UserInfo1.con1("aaa", "11", "id");
}
// 支持java的构造方法形式
class UserInfo {
late String name;
String? age;
String id = "";
UserInfo(String name, String age) {
this.age = age;
this.name = name;
}
}
对于Dart语言本身,他的构造方法有个更简单的写法
与此同时,为了弥补不能重载构造函数的问题,Dart语言引入了建造者模式的设计模式,允许通过重命名的方式来设置多个构造函数。
//Dart自己的构造方法形式
class UserInfo1 {
late String name;
String? age;
String id;
// 构造函数直接填入成员变量,不需要再写赋值,是语法糖
UserInfo1(this.name, {this.age, this.id = ""});
UserInfo1.con1(this.name, this.age, this.id); //命名为con1的另一个构造方法
UserInfo1.con2() : name = "1", age = "2", id = "3"; // 重命名,但是拥有默认实现
}
4.2 访问权限
Dart中没有public potect和private关键字,而是通过在成员变量前面增加_来标记他为私有成员变量,
注意,Dart的私有成员变量指的是本文件以外的对象无法访问,和Java中的本对象以外的对象无法访问不完全相同。
与此同时,对于私有成员变量他的set和get方法写法也略微有区别。
class PrivateUserInfo {
String? name;
String? _age; //私有化,但是dart的私有化是该文件内可以访问,其他文件不能访问
PrivateUserInfo(this.name, this._age);
get getAge {
return _age;
}
set setAge(String age) {
this._age = age;
}
}
PrivateUserInfo在ClassDemo1.dart,ClassDemo2就无法访问了。
私有类也是同理,在类名前面加上下划线,这里不写案例。
4.3 类的继承
和Java同款,唯一区别是,dart语言中没有interface关键字,对于类来说,无论是extends还是implementation,他所继承的都是类。
class c1 {
String? str1;
void fun1() {
}
}
abstract class c2 {
String? str2;
void fun2();
}
class c3 extends c2 implements c1 {
String? str1; // 因为implementation,必须加上c1的成员变量
void fun1() { // 因为implementation,必须加上c1的方法
}
void fun2() { // 因为c2的fun2是抽象方法,必须进行实现
}
}
参考资料
https://blog.csdn.net/haodawang/article/details/83031378