目录
Dart中的函数 函数的定义 可选参数 默认参数 命名参数 箭头函数 匿名函数 闭包
内置方法/函数:就是系统自带的方法,比如一直用的打印方法: print();
Dart中的函数 函数的定义 可选参数 默认参数 命名参数 箭头函数 匿名函数 闭包
Dart中的函数分为两种,内置函数和自定义函数。
内置方法/函数:就是系统自带的方法,比如一直用的打印方法: print();
自定义方法:
自定义方法的基本格式:
返回类型 方法名称(参数1,参数2,...){
方法体
return 返回值;
}
如:
//一个无返回类型的自定义方法
void printInfo(){
print('我是一个自定义方法');
}
//一个有返回类型的自定义方法
int getNum(){
var myNum=123;
return myNum;
}
自定义方法可以写在main()方法里,也可以现在main方法外,void表示是无返回类型的方法,返回类型可以是任意类型,但是需要与返回值保持一直:
//返回类型为String的函数
String printUserInfo(){
return 'this is str';
}
//返回类型为List的函数
List getList(){
return ['111','2222','333'];
}
Dart中的函数的调用
在dart中所有函数都要在入口函数main()中执行
如:(main()中的方法皆为上文中定义出来的方法)
void main(){
print('调用系统内置的方法');
printInfo();
var n=getNum();
print(n);
print(printUserInfo());
print(getList());
}
方法的作用域
void main (){
void xxx(){
aaa(){
print(getList());
print('aaa');
}
aaa();
}
// aaa(); 错误写法,超出aaa()方法的作用域
xxx(); //调用方法
}
}
如上所示,方法内是可以嵌套方法的,但是在xxx()方法内定义的方法,只可以在本方法内部调用,如果写在外面,会提示找不到该方法;但是可以在aaa()中调用getList()方法,因为getList()的作用域是全局的;
Dart中调用方法传参
1、定义一个方法 求1到这个数的所有数的和
int sumNum(int n){//一般建议规定好参数类型
var sum=0;
for(var i=1;i<=n;i++)
{
sum+=i;
}
return sum;
}
var n1=sumNum(5);//传入参数5,即显示1到5的和
print(n1);//输出结果:15
var n2=sumNum(100);//传入参数5,即显示1到100的和
print(n2);//输出结果:5050
2、定义一个方法然后打印用户信息
String printUserInfo(String username,int age){ //形参
return "姓名:$username---年龄:$age";
}
print(printUserInfo('张三',20)); //实参
//输出结果:姓名:张三---年龄:20
写在方法里的参数,称为形参,具体传入的参数,称为实参;
3、定义一个带可选参数的方法
String printUserInfo(String username,[int age]){ 写在[]里的参数,为可选参数
if(age!=null){
return "姓名:$username---年龄:$age";
}
return "姓名:$username---年龄保密";
}
print(printUserInfo('张三',21)); //输出结果:姓名:张三---年龄:21
print(printUserInfo('张三'));//输出结果:姓名:张三---年龄保密
4、定义一个带默认参数的方法
String printUserInfo(String username,[String sex='男',int age]){//[]中的参数如果有默认值,则为默认参数
if(age!=null){
return "姓名:$username---性别:$sex--年龄:$age";
}
return "姓名:$username---性别:$sex--年龄保密";
}
print(printUserInfo('张三'));//输出结果: 姓名:张三---性别:男--年龄保密
5、定义一个命名参数的方法
String printUserInfo(String username,{int age,String sex='男'}){ //注意:这里是{}
if(age!=null){
return "姓名:$username---性别:$sex--年龄:$age";
}
return "姓名:$username---性别:$sex--年龄保密";
}
print(printUserInfo('张三',age:20,sex:'未知'));//{}中的参数也可选填,但是要传参时需要"参数名:参数"这样的格式
//输出结果:姓名:张三---性别:未知--年龄:20
6、实现一个 把方法当做参数的方法
fn1(){
print('fn1');
}
//方法
fn2(fn){
fn();
}
//调用fn2这个方法 把fn1这个方法当做参数传入
fn2(fn1);//输出结果:fn1
Dart中的箭头函数
方法体中只能写一句话,例如
使用forEach打印下面List里面的数据:常规写法
List list=['苹果','香蕉','西瓜'];
list.forEach((value){
print(value);
});
改为箭头函数:
List list=['苹果','香蕉','西瓜'];
list.forEach((value)=>print(value));
或者
List list=['苹果','香蕉','西瓜'];
list.forEach((value)=>{
print(value)//注意,这里不写 ;
});
Dart中方法间的互相调用
需求:定义一个方法打印1-n以内的所有偶数
思路:定义一个方法isEvenNumber来判断一个数是否是偶数 ,再定义一个方法printNum()来输入要打印的范围;
bool isEvenNumber(int n){
if(n%2==0){
return true;
}
return false;
}
printNum(int n){
for(var i=1;i<=n;i++){
if(isEvenNumber(i)){
print(i);
}
}
}
printNum(10);
这样,就实现了方法间的互相调用
Dart中的匿名函数
一般定义函数都是有名字的,如之前定义的isEvenNumber(int n),而匿名函数的语法格式如下:
void main(){
//不带参数的匿名方法
var printNum=(){
print(123);
};
printNum();
//带参数的匿名方法
var printNum=(int n){
print(n+2);
};
printNum(12);
使用的方法和普通函数一样。
Dart中的自执行方法
自执行方法:顾名思义,就是不用主动去调用,让这个程序一加载就自己执行的方法。
语法格式:使用两个(),在第一个括号里写一个匿名函数,其中前面的括号里定义形参,第二个()里传入实参
((int n){
print(n);
print('我是自执行方法');
})(66);
打印结果:66 我是自执行方法
Dart中方法的递归
递归及一个方法调用自己,注意要设置结束调用的填写
需求1:求n的阶乘
示例代码:
var sum=1;
fn(n){
sum*=n;
if(n==1){
return ;
}
fn(n-1);
}
fn(5);
print(sum);
需求2:求n的阶乘通过方法的递归 求1-100的和
var sum=0;
fn(int n){
sum+=n;
if(n==》=100){//设置结束递归的条件
return //设置要返回的值
}
fn(n-1);
}
fn(100);
print(sum);//输出结果:5050
Dart中的闭包
了解闭包之前,先看全局变量和局部变量的特点:
1、全局变量特点: 全局变量常驻内存、全局变量污染全局(即不会被垃圾回收机制回收,而且可以被其他的函数引用,修改,容易造成程序里未知错误);
2、局部变量的特点: 不常驻内存会被垃圾机制回收、不会污染全局
所以如果想常驻内存又不想不污染全局时,就有了闭包的操作;
那什么是全局变量和局部变量呢?
例如:
/*全局变量演示*/
var a=12;
void main(){
print(a);
fn(){
a++;
print(a);
}
fn();//输出结果:13
fn();//输出结果:14
fn();//输出结果:15
//由此可见,a是常驻内存的,因此像这样的变量,称为全局变量
//局部变量演示
printInfo(){
var myNum=13;//其中myNum就是局部变量。他的作用域仅限于这个方法,在这个方法外不能被调用
myNum++;
print(myNum);
}
printInfo();//输出结果:14
printInfo();//输出结果:14
printInfo();//输出结果:14
/*可以看到,每次调用完printInfo()方法后,myNum就被回收了,下次调用的时候,又是一个新的myNum,
所以每次结果都14,即13+1,这样的变量称为局部变量*/
闭包: 函数嵌套函数, 内部函数会调用外部函数的变量或参数, 变量或参数不会被系统回收(不会释放内存)
闭包的写法: 函数嵌套函数,并return 里面的函数,这样就形成了闭包。
示例代码:
printInfo(){
var myNum=13;
return(){//这里其实是一个匿名函数
myNum++;
print(myNum);
};
}
var b = printInfo();//定义一个变量b来接受返回的函数
b();//输出结果:14
b();//输出结果:15
b();//输出结果:16
/*可以看到,myNum是一个局部变量,不会污染全局。但是每次调用结束的时候,也不会被系统回收,
这样就完成了闭包*/
Dart面向对象的介绍 以及Data内置对象
面向对象编程(OOP)的三个基本特征是:封装、继承、多态
封装:封装是对象和类概念的主要特性。封装,把客观事物封装成抽象的类,并且把自己的部分属性和方法提供给其他对象调用, 而一部分属性和方法则隐藏。
继承:面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
多态:允许将子类类型的指针赋值给父类类型的指针, 同一个函数调用会有不同的执行效果 。
Dart所有的东西都是对象,所有的对象都继承自Object类。
Dart是一门使用类和单继承的面向对象语言,所有的对象都是类的实例,并且所有的类都是Object的子类
一个类通常由属性和方法组成。
/*
比如之前用到过的List,Map等,其本质就是一个类
*/
void main(){
List list=new List();
list.isEmpty;
list.add('香蕉');
list.add('苹果');
/* 比如,在List类中,为我们提供了.add(),.isEmpty()等方法*/
Map m=new Map();
m["username"]="张三";
m.addAll({"age":20});
m.isEmpty;
Object a=123;
print(a);
}
Dart中自定义类的创建和使用
我们来自定义一个Person类。
class Person{//使用关键字class来定义一个类
String name="张三";//为person类添加一个属性name;
int age=23;
void getInfo(){//定义一个方法getInfo()来打印这个类里的属性;
//两种引用属性的方法
print("$name----$age");
print("${this.name}----${this.age}");//this关键字表示当前类
}
void setInfo(int age){//定义一个方法setInfo()来为这个类里的属性赋值;
this.age=age;
}
}
//类的使用
void main(){
//首先必须实例化,在dart中,new关键字可以省略。
var p1=new Person();
//如果像调用类里面的name属性,那么就可以直接用p.name获取,获取方法同理
print(p1.name);//输出结果:张三
p1.getInfo();//输出结果:张三 ----23
Person p2=new Person();
//同时,也可以通过类里的方法,对属性进行修改
p1.setInfo(28);//调用setInfo方法,修改age的值
p1.getInfo();//输出结果:张三 ----28
}
Dart中自定义类的默认构造函数
默认构造函数一般和类同名,并且在实例化的时候自动被调用,如:
class Person{
String name='张三';
int age=20;
//默认构造函数
Person(){
print('这是构造函数里面的内容 这个方法在实例化的时候触发');
}
void printInfo(){
print("${this.name}----${this.age}");
}
}
void main(){
/*此时,只要实例化Person类后,就会输出内容:
'这是构造函数里面的内容 这个方法在实例化的时候触发'*/
var p1=new Person();
}
如果想让Person类打印任何人的信息,就可以这样写:
class Person{
String name;
int age;
//默认构造函数
Person(String name,int age){
this.name=name;
this.age=age;
}
void printInfo(){
print("${this.name}----${this.age}");
}
}
//此时,在main方法中实例化Person类的时候,就需要传入要打印的信息,如:
void main(){
var p1=new Person(’张三’,12);
p1. printInfo();//输出结果:张三----12
//类可以进行多次实例化,比如现在又想打印李四的信息,只要在初始化一个对象p2
var p2 = Person('李四',34)
p2.printInfo();//输出结果:李四----34
}
默认构造函数的简写
class Person{
String name;
int age;
//默认构造函数的简写
Person(this.name,this.age);
void printInfo(){
print("${this.name}----${this.age}");
}
}
Dart中自定义类的命名构造函数
dart里面构造函数可以写多个,但是默认构造函数只能写一个,语法:
类名.方法名(){};如:
class Person{
String name;
int age;
//默认构造函数
Person(this.name,this.age);
//命名构造函数
Person.now(){
print('我是命名构造函数');
}
//命名构造函数
Person.setInfo(String name,int age){
this.name=name;
this.age=age;
}
void printInfo(){
print("${this.name}----${this.age}");
}
}
void main(){
var d=new DateTime.now(); //实例化DateTime调用它的命名构造函数
print(d);
Person p1=new Person('张三', 20); //默认实例化类的时候调用的是 默认构造函数
Person p1=new Person.now(); //命名构造函数
Person p2=new Person.setInfo('李四',30);
p2.printInfo();
}
Dart中把类单独抽离成一个模块
在实际开发中,为了可维护性,一般会将一个类抽离出来一个单独的.dart文件。这样做的好处就是,可以在任意地方,通过import关键字来导入这个类就可以使用,单个文件内代码也不会过于冗余。便于多人开发。
如:我在lib文件夹下,新建一个Person.dart文件,将刚才Person类的内容剪贴进去
使用的时候:
import 'lib/Person.dart';
void main(){
Person p1=new Person.setInfo('李四',30);
p1.printInfo();//输出结果:李四----30
}
我在使用AndroidStudio时,虽然将文件放在了lib目录下,但是import的路径为:'package:项目名/Person.dart';
Dart中的私有方法 和私有属性
Dart和其他面向对象语言不一样,Data中没有 public private protected这些访问修饰符号,但是我们可以使用_把一个属性或者方法定义成私有。
首先我们新建一个Animal类:
class Animal{
String _name; //私有属性
int age;
//默认构造函数的简写
Animal(this._name,this.age);
void printInfo(){
print("${this._name}----${this.age}");
}
void _run(){
print('这是一个私有方法');
}
}
这样name属性和run()方法都是私有方法,私有的方法和属性不能直接被调用,只能在方法内调用。因此我们需要在类里在定义几个方法,来间接的获取私有方法和属性。
class Animal{
String _name; //私有属性
int age;
//默认构造函数的简写
Animal(this._name,this.age);
void printInfo(){
print("${this._name}----${this.age}");
}
String getName(){
return this._name;
}
void _run(){
print('这是一个私有方法');
}
execRun(){
this._run(); //类里面方法的相互调用
}
}
通过添加方法getName()和 execRun(),就可以在main()中调用Animal内的私有属性和方法,如:
void main(){
Animal a=new Animal('小狗', 3);
//print(a._name)这样写,程序会报错,因为_name为私有属性,只能在Animal类里被调用
//此时需要调用公共方法getName()来间接的调用私有属性
print(a.getName());
a.execRun(); //间接的调用私有方法
}
类中的get和set修饰符的用法
我们定义一个Rect类,在Rect中有输出面积和输入长宽的方法。使用get定义的时候,方法后面没有(),相当于计算属性,调用的时候跟调用属性的方式一样。set使用和get类似。下面是常规写法和使用get/set的对比:
class Rect{
num height;
num width;
Rect(this.height,this.width);
//常规方法定义
area(){
return this.height*this.width;
}
//使用get定义方法:
get area{
return this.height*this.width;
}
//使用set定义方法
set areaHeight(value){
this.height=value;
}
}
定义方式不同,调用的方式也会不同:
void main(){
Rect r=new Rect(10,4);
print("面积:${r.area()}"); //常规调用方法
print("面积:${r.area}"); //注意调用直接通过访问属性的方式访问area
r.areaHeight=6; //调用使用set定义的方法,也相当于一个属性
print("面积:${r.area}"); //在打印时就会输出:60
}
类中的初始化列表
Dart中我们也可以在构造函数体运行之前初始化实例变量
class Rect{
int height;
int width;
Rect():height=2,width=10{//初始化列表操作
print("${this.height}---${this.width}");
}
getArea(){
return this.height*this.width; }
}
void main(){
Rect r=new Rect();//此时,就会输出2----10,说明在实例化之前,就已经给属性赋值了
print(r.getArea());
}