Flutter的Dart语法入门

前言

每个语言都有控制流语句就不写测试代码了。

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

附录

相关推荐

  1. Flutter入门学习——FlutterDart

    2024-06-06 22:10:03       24 阅读
  2. Dart语言泛型

    2024-06-06 22:10:03       8 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-06 22:10:03       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-06 22:10:03       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-06 22:10:03       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-06 22:10:03       18 阅读

热门阅读

  1. 嵌入式学习——网络编程(UDP)——day30

    2024-06-06 22:10:03       9 阅读
  2. iPhone 语言编程:深入探索与无限可能

    2024-06-06 22:10:03       11 阅读
  3. iOS swift5 加载网络图片的第三方框架

    2024-06-06 22:10:03       8 阅读
  4. C++ 智能指针

    2024-06-06 22:10:03       10 阅读
  5. Docker命令大全

    2024-06-06 22:10:03       10 阅读