Flutter开发之Dart语言
返回类型 方法名称(参数1,参数2,...){方法体return 返回值;在Dart中,定义一个类可以使用class关键字,后面跟着类名,然后是类体,包含在一对花括号中。类体内部可以包含属性、构造函数、自定义方法。//自定义属性(又名实例属性、实例变量、成员变量)String?name;int?age;//自定义方法sex){
Dart是Flutter框架的官方开发语言,Flutter应用几乎完全使用Dart编写。Flutter的跨平台特性使得Dart在移动应用开发中非常受欢迎。Dart是面向对象的、类定义的、单继承的语言,支持面向对象编程,包括封装、继承和多态等特性;
Dart支持接口(interfaces)、混入(mixins)、抽象类(abstract classes)、具体化泛型、可选类型。Dart中很多概念跟其他语言基本一致。
目录
一、常量与变量
1. 常量
Dart的常量使用 const 和 final 修饰,赋值后不可更改。
const:必须在声明时赋值,且值在编译时确定(编译常量),不能是计算值;
final:可以在声明时赋值;也可以选择不赋值,后续赋值,只可赋值一次。
编译常量:可以在编译时就能确定其值,那么可以将其视为编译时常量
运行时常量:计算值,即在被使用到的时候才会进行初始化
void main() {//程序入口方法
const p = 3.14;//定义时必须初始化,编译常量
final q; q = 3.14;//可以后赋值,编译常量
final time = new DateTime.now();//可以用方法返回值赋值,运行时常量
print(time);//每次打印时time被初始化打印当前时间
}
2. 变量
通过var关键字声明变量(类型推断),也可通过显式类型String,int等来声明
String name; int age;//显式类型定义
String? name2; int? age2;//使用?来声明可空类型,变量可以赋值为null。
var myName = 'lucy';//赋值后类型确定
var map = {'key':'value'};//定义Map、List对象类型
var studentName, studentAge, studentHeight;//同时声明多个变量,用逗号分隔
二、数据类型
Dart是一种面向对象、强类型的程序设计语言,所有类型都是对象。常见的数据类型有int,double,num,String,bool,List,Map,null
1. int、double、num
num为int、double的父类,可以赋值任意数字类型
int x = 2;
double y = 2.5;
double y2 = 3;// 即使没有小数部分,也默认为double类型
print(y2);//打印结果:3.0
//num是int和double的父类,它可以存储任何数值(整数和浮点数)
num z = 2;//num赋值后类型可变,随值类型可变化
print(z.runtimeType);//打印结果:int
z = 2.5;//num赋值后类型可变,随值类型可变化
print(z.runtimeType);//打印结果:double
2. String
字符串String定义可以使用单引号、双引号、单三引号、双三引号,其中三引号可以定义换行的字符串。
String s1 = 'this is str1';
String s2 = "this is str2";
String s3 = '''this is str3''';
String s4 = """this is str4
this is str4
this is str4""";//这将允许您在字符串中直接嵌入换行符,而不需要使用 \n。
print(s4);//打印结果会换行打印
字符串常见操作如下:
//1.字符串拼接
String str1 = 'Hello, ';
String str2 = 'World!';
String pinjie1 = str1 + str2;//方式1,打印结果:Hello, World!
String pinjie2 = '$str1$str2';//方式2,打印结果:Hello, World!
//2.字符串长度、字符串大小写
var str = 'Hello, World!';
var length = str.length; //长度,打印结果:13
var upper = str.toUpperCase(); // 打印结果:'HELLO, WORLD!'
var lower = str.toLowerCase(); // 打印结果:'hello, world!'
//3.字符串分割
var names = 'jack,lucy,lili';
var nameList = names.split(', '); // 打印结果:[jack,lucy,lili]
//4.判断包含
var test = 'Hello, World!';
var index = test.indexOf('X'); // 判断字符串位置,为-1不包含
var isHasX = test.contains('Hello');//打印结果:true
//5.字符串替换、截取
var newStr = test.replaceAll('World', 'Dart'); // 'Hello, Dart!'
var substring = newStr.substring(7, 12); //substring接受一个或两个参数:一个是开始索引,另一个是可选的结束索引。
var substring2 = newStr.substring(7); //只提供开始索引,则substring会从开始索引到字符串末尾提取子串。
print(substring);//打印结果:Dart!
3. bool
同其他语言一致,使用bool、var定义
bool isTrue = true;
var isFalse = false;
if(isTrue){
print(isFalse);//false
}
4. List
List 是一个有序的集合[ ],可以包含重复的元素。可以通过索引来访问和修改列表中的元素。与之对应的Set不常用,为无序的,不可重复集合{ }.
List常用操作如下:
//1.创建List
var list = [1, 2, 3]; // var创建一个List
List<String> list2 = ['Hello', 'World']; // 创建一个指定类型的List
//2.添加
list.add(4);//末尾添加元素[1, 2, 3, 4]
list.insert(1, 5);//在指定索引插入元素 [1, 5, 2, 3, 4]
//3.删除
list.remove(4);//删除指定元素[1, 5, 2, 3]
list.removeAt(1);//删除指定位置[1, 2, 3]
//4.连接
var newList = list + [9,8,7];//[1, 2, 3, 9, 8, 7]
//5.排序
newList.sort();// [1, 2, 3, 7, 8, 9]
//6.遍历
newList.forEach((element) {
print(element);//123789
}); // 遍历List中的所有元素
5. Map
Map 是一种集合类型,用于存储键值对形式的数据。
//1.创建Map
var map1 = {
'key1':'value1',
'key2':'value2',
};
Map<String, dynamic> map2 = Map();
//2.添加键值对
map1['key3'] = 'value3';
map1.addAll({
'key4':'value4',
'key5':'value5'
});
//3.删除键值对
map1.remove('key1');
//4.判断包含
map1.containsKey('key1');
//5.遍历
map1.forEach((key, value) {
print('$key: $value');
});
6.可空类型
使用 ? 后缀可以创建可空类型,允许变量可能为 null。例如:String?、int?
使用??、!取出其值;
使用?. 、!.来访问它的属性或调用它的方法;
String? name = 'lucy';
String displayName = name ?? 'lucy2';//??判断name是否为空,不为空取出name值;为空,将lucy2赋值给displayName
String displayName2 = name!;//非空断言,已知非空,取出name值
print(name?.length);//name为空不会调用方法,不会异常
print(name!.toUpperCase());//非空断言,已知非空,调用方法;若为空使用!异常
7. 类型判断is
is运算符来检查一个对象是否是特定类型的实例。如果对象是指定类型的实例,is运算符将返回true,否则返回false
var num = 123;
// 检查num是否是String类型的实例
if (num is String) {
print('num是String类型');
} else {
print('num不是String类型');
}
8.类型转换as
类型转换通常使用as关键字进行。as为强制转换,如果转换失败,会抛出异常,应确保类型正确;
dynamic value = "123"; // 假设这是一个可能是字符串也可能是其他类型的变量
// int number = value as int; // 尝试将其转换为int类型,异常
if (value is String) {
String values = value as String;
}
常用的数字与字符串之间的转换
String integerString = '12345';
String doubleString = '123.45';
int integerValue = int.parse(integerString);// 转换为整数输出: 12345
double doubleValue = double.parse(doubleString);// 转换为双精度浮点数 输出: 123.45
String newIntegerString = integerValue.toString();
String newDoubleString = doubleValue.toString();
三、运算符
Dart支持一般语言的运算符:
算术运算符:加法 +、减法 -、乘法 *、除法 /、取余 %、取整 ~/
关系运算符:等于 ==、不等 !=、大于 >、小于 <、大于等于 >=、小于等于 <=
逻辑运算符:取反!、且 &&、或 ||
复合赋值运算符(+=,-=,*=,/=,%=,~/=,??=)
三目运算( ?:)、??运算、as(类型转换),is(类型判断)
String? name;
name ??= 'test';//如果左边的操作数为null,则将其赋值为右边的操作数;否则保持不变。
name = name ?? 'test2';//与上同
print(name);//test
四、条件语句、循环语句
Dart支持一般语言的条件语句、循环语句:
条件语句:if.. else.. switch.. case..
循环语句:for.. while.. do..while..
不再赘述
五、函数
Dart 中的函数与一般语言的函数定义相同。
1. 函数的定义
返回类型 方法名称(参数1,参数2,...){
方法体
return 返回值;
}
2. 函数的参数
在Dart中函数的参数有一些新的定义
2.1. 位置可选参数
位置可选参数:在参数中用中括号[ ] 包含的参数,一般写在默认参数后方;调用的时候可以不带[ ]中的参数,也可以按序带上[]上的部分或全部参数;([]内不可跳跃传参)
String getName(String name,[int? age, String? sex]){
return "name : $name ; age : $age ; sex : $sex";
}
String test1 = getName('xiaoming');// name : xiaoming ; age : null ; sex : null
String test2 = getName('xiaoming',18);//xiaoming ; age : 18 ; sex : null
// String test3 = getName('xiaoming','男');//报错,传参错误
String test4 = getName('xiaoming',null,'男');//xiaoming ; age : null ; sex : 男
String test5 = getName('xiaoming',18,'男');//xiaoming ; age : 18 ; sex : 男
2.2. 命名可选参数
命名可选参数:在参数中用{ }包含的参数,一般写在默认参数后方;调用的时候可以不带{}中的参数,也可以带上{}上的部分或全部参数;(需要传递参数名)
String getName(String name,{int? age, String? sex}){
return "name : $name ; age : $age ; sex : $sex";
}
String test1 = getName('xiaoming');//xiaoming ; age : null ; sex : null
String test2 = getName('xiaoming',age: 18);//xiaoming ; age : 18 ; sex : null
String test3 = getName('xiaoming',sex: '男');// xiaoming ; age : null ; sex : 男
String test4 = getName('xiaoming',age: 18,sex: '男');//xiaoming ; age : 18 ; sex : 男
2.3. 可选参数默认值
可选参数可以通过"="赋一个默认值;默认值在该参数传参后更改
String getName(String name,[int age = 20, String? sex]){
return "name : $name ; age : $age ; sex : $sex";
}
String test1 = getName('xiaoming');// name : xiaoming ; age : 20 ; sex : null
String test2 = getName('xiaoming',18);//name : xiaoming ; age : 18 ; sex : null
String getName2(String name,{int age = 20, String? sex}){
return "name : $name ; age : $age ; sex : $sex";
}
String test3 = getName2('xiaoming',sex: '男');// name : xiaoming ; age : 20 ; sex : 男
String test4 = getName2('xiaoming',age: 18,sex: '男');// name : xiaoming ; age : 18 ; sex : 男
3. 匿名函数
Dart 中的函数也是对象,并且有它的类型 Function 。 这意味着函数可以被赋值给变量或者作为参数传递给其他函数。
匿名函数,顾名思义,即是没有名字的函数
Function f = (String name){
var t = 'name:' + name;
print(t);
};
f('xiaoli');//name:xiaoli
在传参的时候,把匿名函数作为参数传递,内部调用该函数,实现回调功能。
六、类
1. 类的定义
在Dart中,定义一个类可以使用class关键字,后面跟着类名,然后是类体,包含在一对花括号中。类体内部可以包含属性、构造函数、自定义方法。
class Person {
//自定义属性(又名实例属性、实例变量、成员变量)
String? name;
int? age;
//自定义方法
getInfo(String? sex){
print('name:$name age: $age sex:$sex');
}
}
2.类的属性
类的属性用于存储对象的状态或数据,可以是实例变量、私有变量、静态变量。
2.1 实例变量
所有实例变量都会生成一个隐式的getter、setter方法。所有未初始化的实例变量的默认值都为null。实例变量需要保证空安全,需要加?可空类型或者late延迟初始化。
可以使用get、set关键字添加新的getter、setter,不影响原getter、setter。
class Person {
//保证空安全:实例属性需要加可空标志?或者 late(延迟初始化)
String? name;
int? age;//变量可空标志?
late String sex;//变量延迟初始化
late final String nickName;//常量必须初始化或添加late,只可赋值一次
get myName{
return name;
}//用get修饰的方法块,使用的时候通过调用属性的方式使用
set shezhiName(newName){
name = newName;
}//通过“对象.属性 = 值”的方式调用set修饰的方法体
//自定义方法
getInfo(String? sex){
print('name:$name age: $age sex:$sex nickName:$nickName');
}
}
var person = Person();
person.name= 'lucy';
person.nickName = 'baobao';//final修饰可以被初始化一次
person.getInfo(null);// name:lucy age: null sex:null nickName:baobao
print(person.myName);//打印结果:lucy 用get修饰的方法块,使用的时候通过调用属性的方式使用
print(person.name);//打印结果:lucy 添加get方法不影响原get
person.shezhiName = 'jack';//通过“对象.属性 = 值”的方式调用set修饰的方法体
print(person.name);//打印结果:jack
person.name = 'leilei';
print(person.name);//打印结果:leilei 添加set方法不影响原set
2.2 私有变量
私有属性是通过在属性名前加上下划线(_)来定义的。这种属性只能在定义它们的类内部访问,不能在类的外部直接访问。(私有方法同理)
class Person {
String? _name;
setName(value){
_name = value;
}
getInfo(){
print('name:$_name');
}
}
var person = Person();
person.setName('lucy');
person.getInfo();//name:lucy
2.3 静态变量
类的静态变量是该类的所有实例共享的变量,通过类名访问静态变量。使用static 关键字来实现类级别的变量。(静态方法同理)
非静态方法可以访问静态成员;静态方法不能访问非静态成员。
class Person {
String? name;
static String? nickName;
getInfo(){
print('name:$nickName');
}
static getInfo2(){
// print('name:$name');//静态方法无法访问实例变量
print('name:$nickName');//只可访问静态变量
}
}
Person.nickName = 'lucy';
var person = Person();
person.getInfo();//打印结果:name:lucy 实例方法获取静态属性
Person.nickName = 'leilei';
Person.getInfo2();//打印结果:name:leilei 静态方法获取静态属性
3.类的构造函数
3.1 默认构造函数
如果没有显式定义任何构造函数,Dart会自动生成一个无参数的默认构造函数。
Person p = Person();//默认构造函数,无法穿参
p.getInfo('男');//name:null age: null sex:男
如果显式定义任何构造函数,默认构造函数就不会生成。
3.2 普通构造函数
使用类名作为函数名来定义构造函数
class Person {
//自定义属性
String? name;
int? age;
Person(String name, int age){
this.name = name;
this.age = age;
}//普通构造函数
//简写Person(this.name,this.age);
//自定义方法
getInfo(String? sex){
print('name:$name age: $age sex:$sex');
}
}
3.3 命名构造函数
命名构造函数允许你为构造函数指定一个名称,这有助于区分不同的构造函数。命名构造函数可以有多个。
class Person {
//自定义属性
String? name;
int? age;
//普通构造函数
Person(this.name,this.age);
// 命名构造函数1
Person.Init(){
print('name:$name age: $age');
}
// 命名构造函数2
Person.fromJson(Map<String, dynamic> json) {
name = json['name'];
age = json['age'];
}
//自定义方法
getInfo(String? sex){
print('name:$name age: $age sex:$sex');
}
}
// 使用普通构造函数
var person1 = Person('Alice', 30);
person1.getInfo(null);//name:Alice age: 30 sex:null
// 使用命名构造函数
var person2 = Person.Init();//name:null age: null
// 使用命名构造函数
var person3 = Person.fromJson({'name': 'Bob', 'age': 25});
person3.getInfo(null);// name:Bob age: 25 sex:null
3.4 工厂构造函数
在构造方法前添加 factory 关键字,使构造方法可以返回值。常用在单例模式
class Person {
static Person? _instace;
factory Person() => _instace ??= Person._init();
Person._init();
}
Person p1 = Person();
Person p2 = Person();
print(p1 == p2);//true
3.5 常量构造函数
常量构造函数指返回不可变对象的构造函数;
主要用途是创建不可变的对象,确保对象的属性在编译时就被确定,并且在运行时无法修改。这种构造函数通过使用const关键字声明,使得对象在编译时就已经确定,从而在运行时无法更改其属性值。创建大量相同对象节省内存。
class Person {
//保证所有的实例变量为final修饰
final String name;
final int age;
//构造函数必须加const,不能有函数体
const Person(this.name, this.age);
}
//参数改变或者不加const,均非同一对象
var p1 = const Person('Jane', 28);
var p2 = const Person('Jane', 28);
print(identical(p1, p2)); // 输出 true,表示 p1 和 p2 是同一个对象
const p3 = Person('John', 30);
const p4 = Person('John', 30);
print(identical(p3, p4)); // 输出 true,表示 p3 和 p4 是同一个对象
3.6 重定向构造函数(构造函数传递)
重定向构造函数用于将调用重定向到同一个类的其他构造函数,或者到从父类继承的构造函数。
调用本类构造函数:
class Person{
String? name;
int? age;
Person(this.name, this.age);
//使用:调用其他构造函数,并可将参数传递
Person.chongdingxiang(String nowName, int nowAge) : this(nowName,nowAge);
}
Person p = Person.chongdingxiang('lucy', 30);
print('name:${p.name} age: ${p.age}');//name:lucy age: 30
在继承关系的子类中,一般需要调用父类的构造函数;这种分2种情况:
隐式调用:父类只有默认构造函数,默认在子类的构造函数前调用父类的构造函数
class Person{
String? name;
int? age;
}
class Student extends Person{
}
Student xiaoming = Student();
显示调用:显式调用父类构造函数,应该在初始化列表中完成
class Person{
String? name;
int? age;
//1.普通构造函数
Person(this.name,this.age);
//2.命名构造函数
Person.myInit(String myName){
this.name = myName;
this.age = 18;
print('Person init');
}
}
class Student extends Person{
String? nickName;
//1.重定向到父类普通构造函数,传递参数
Student(String name, int age) : super(name,age);
//简写Student(super.name, super.age);
//2.重定向到父类命名构造函数,传递参数
Student.myInit2(String nowName) : super.myInit(nowName);
//3.重定向到父类命名构造函数,传递参数,后执行自带函数体(初始化列表)
Student.myInit3(String nowName) : super.myInit(nowName) {
print('Student init');
}
//4.初始化列表:构造函数方法体之前,初始化一些成员变量(重定向到父类普通构造函数)
Student.myInit4(super.name,super.age) : nickName = 'xxx' {
print('Student init');
}
}
常见用例解析:const MyApp({super.key}),综合了常量与重定向构造函数
//简写: const MyApp({super.key});
//展开: const MyApp({Key? key}) : super(key: key);
//如下例子相同:
class Person{
//将参数定义可选?,此时常量构造函数也可用可选命名参数
final String? name;
//常量构造函数
const Person({this.name});
}
class Student extends Person{
//在子类创建普通构造函数重定向到父类常量构造函数
// Student({String? canshu}) : super(name: canshu);
//简写 Student({super.name});
//添加const,定义为子类的常量构造函数;即如常见的类
const Student({super.name});
}
Student s1 = const Student(name: '11');
Student s2 = const Student(name: '11');
print(s1 == s2);//true
更多推荐



所有评论(0)