【Dart】002-函数
〇、学习启动器 1.0
第一步:煮茶(茶包 + 少量茶叶)
第二步:按摩仪按摩眼部 10 分钟;
第三步:倒茶 + 戴上耳机听纯音乐 + 倒计时 10 分钟 + 加告诉自己随时可以停止学习
第四步:后面每 25 分钟为一个周期,每 25 分钟休息 5 分钟,随时可以停止这个循环
注意点:不追求学习的速度,不安排任何学习任务,随时可以停止学习!
一、函数是什么
0、概述
像一个黑箱
函数像一个黑箱,不同的输入,会通过黑箱中的逻辑处理产生一个对应的输出。
数学意义
输入是 自变量 x
, 输出是 因变量 y
,其中黑箱的处理逻辑称为对应法则 f
。三者的关系可以通过 y = f(x)
来表示。
1、编程中的函数与方法
强调的是功能/作用
数学中的 函数
是强调两个 集合
间的映射关系,这对于编程中的函数而言,还是有区别的。编程中并不强制输入和输出的数量,function
更强调的是 作用
和 功能
,其目的是完成特定的 任务
,而非仅是维护映射关系。
完成特定功能的代码段
在 c/c++
中一般称一个功能团(完成特定功能的代码段)为 函数 function
,在 java
的类中,一般称一个功能团为 方法 method
。它们都是完成特定任务的代码段。
2、函数的定义
在
dart
中,定义函数并不需要关键字。
语法格式
返回值类型 方法名(参数类型 参数名){
方法体;
}
简单演示
int square(int x) {
return x * x;
}
省略 返回值类型
和 参数类型
(不推荐)
square(x) {
return x * x;
}
3、函数的简写:箭头函数
当函数体中只要一行表达式时,可以通过
=>
进行简写,返回表达式的值!闲聊*:这种写法和
ts
是一样的,java
的箭头函数是->
,我的日常工作中,写习惯了前端,忽然写java
代码会不习惯。虽然我是一个以后端为主的程序员,但在前端花费的时间常常更多!
代码演示
int square(int x) => x * x;
二、函数的参数与调用
0、概述
不同的编程语言有不同的参数特性,对于 Dart
而言,支持 命名参数
、位置参数
、默认参数
,总的来说还是比较丰富的。
闲聊*:各种参数带来了编程的灵活性,
java
在这方面我觉得就比较欠缺,很多时候我很喜欢带默认值的参数!
1、多个参数
代码演示
void solution(int n, int m) {
print("头数:$n 足数:$m");
int y = (m - n * 2) ~/ 2;
int x = n - y;
print("雉数:$x 兔数:$y");
}
void main() {
solution(35, 94);
}
运行结果
头数:35 足数:94
雉数:23 兔数:12
2、命名参数的作用
语义更加明确
它可以使 语义更加明确
,在函数定义时,通过 {}
可以设为命名参数。
调用函数的时候:solution(head: 35, foot: 94);
闲聊*:确实是语义明确了,但是也增加了代码量,我在编写
java
代码时使用的IntelliJ IDEA
是带提示的!
void solution({
required int head,
required int foot,
}) {
print("头数:$head 足数:$foot");
int y = (foot - head * 2) ~/ 2;
int x = head - y;
print("雉数:$x 兔数:$y");
}
void main() {
solution(head: 35, foot: 94);
}
无需按照参数顺序进行传递
闲聊*:表面意思,这个好像有点用吧!毕竟都是命名参数了,只要写了肯定能对应上。
void solution({
required int head,
required int foot,
}) {
print("头数:$head 足数:$foot");
int y = (foot - head * 2) ~/ 2;
int x = head - y;
print("雉数:$x 兔数:$y");
}
void main() {
// 不用按顺序写
solution(foot: 94, head: 35);
}
3、默认参数
概述
在命名参数中设置参数的默认值。
语法格式
{类型 参数名 = 默认值}
代码演示
void solution({
// 此处不能使用 required 关键字,都有默认值了,所以不传参数也可以
int number = 10
}) {
print(number);
}
void main() {
// 带参数调用
solution(number: 35);
// 不带参数调用
solution();
}
运行结果
35
10
4、位置参数
概述
位置参数通过 [参数1,参数2,...]
来指定,其特点是必须按顺序
依次进行指定若干入参。正是因为这种特性,一般来说用于参数有前后顺序的场景。
代码演示
void main() {
print(DateTime(1996, 4, 27));
}
运行结果
1996-04-27 00:00:00.000
三、函数类型
0、概述
函数可以通过 typedef
定义类型,如下定义了一个 Operation
类型,表示一种入参是 double
,返回值是 double
的函数。
typedef Operation = double Function(double);
闲聊*:这种东西挺新的!在
ts
中有类似的东西!ts
的调用签名(我的ts
学得并不好!)。
1、函数对象的声明和使用
代码演示
// 函数类型
typedef Operation = double Function(double);
// 函数
double square(double a) {
return a * a;
}
main(){
// 函数对象定义
Operation op = square;
// 调用函数对象:下面两种写法效果一样!
// 和直接调用 square 函数的效果一样!
print(op(2));
print(op.call(2));
}
运行结果
4.0
4.0
有什么好处
通过函数类型,可以让我们把函数当做 对象
来看待,这就表示 op
变量可以在编程中指代其他符合方法签名的其他函数。
哦!方法签名!哈哈!具体使用时的强大作用,可能要在具体使用的时候去体会了!
// 函数类型
typedef Operation = double Function(double);
// 函数
double square(double a) {
return a * a;
}
// 函数
double cube(double a) {
return a * a * a;
}
main(){
// 函数对象定义
Operation op = square;
// 调用函数对象:下面两种写法效果一致
print(op(2));
print(op.call(2));
Operation op1 = cube;
print(op1(2));
print(op1.call(2));
}
// 4.0
// 4.0
// 8.0
// 8.0
2、函数类型方法参数
把函数作为其他函数的参数
函数既然可以当做 对象
看待,那自然就可以作为函数的入参,这也是函数类型的价值体现。
其中
?
表示该入参可为空。下面并不是一定要用
{}
这只是命名参数写法罢了!
double add(double a, double b, {Operation? op}) {
if (op == null) return a + b;
return op(a) + op(b);
}
直接提供一个匿名函数
直接提供一个函数,那么就不用传这个参数了!
double add(double a, double b, op: (double e) => e * e) {
if (op == null) return a + b;
return op(a) + op(b);
}
完整代码演示
// 函数类型
typedef Operation = double Function(double);
// 函数
double square(double a) {
return a * a;
}
// 函数
double cube(double a) {
return a * a * a;
}
double add(double a, double b, Operation? op) {
if (op == null) return a + b;
return op(a) + op(b);
}
main(){
// 函数对象定义
Operation op = square;
// 调用函数对象:下面两种写法效果一致
print(op(2));
print(op.call(2));
Operation op1 = cube;
print(op1(2));
print(op1.call(2));
print(add(2, 4, square));
}
运行结果
4.0
4.0
8.0
8.0
20.0
3、函数的作用
函数本质上是对实现某特定功能的代码段的封装,以实现共享。这种共享有利有弊,好处在于,普通的开发者即使能力不强,也可以通过引入三方库,或者复制粘贴来完成功能需求。这就大大降低了编程中实现功能的门槛,也有利于集中人类智慧去共同解决一些问题。**弊在于,**理想很丰满,显示很骨感。就像吃大锅饭一样,这会导致很大一批人,过于依赖别人,缺乏自主思考的能力,当出现问题或找不到库时,就举步维艰。