先说下我学习Dart函数的感受吧,我尝试用java语言的形式去学习Dart,但是令我意外的是,我刚迈出第一步Dart就把我踢出门外。什么意思呢?比如说,在Java中我们可以重载函数,但是Dart它没有,再比如说返回值类型,在Java中我们必须特定的给出,不然Java编译器它不认识,但是Dart不一样,Dart我们可以不指定返回值类型。总之,就是感觉学起来特别的有意思,可能是因为Dart在不断的给我惊喜吧,让我有了想不断去探索的决心。
一、普通函数
1.指定返回值得函数
-
/**
-
* 无返回值的函数
-
* params: 可以是任意类型(var和Object类型也可以任意类型)。 当然这里的参数类型你可以随意指定我这里已dynamic为例
-
* 参数类型:你也可以指定var、Object等,再比如说你可以指定num, int,double, String....
-
* 如果我们对参数没有限制的话可以使用这个
-
*/
-
void printDynamicParams(dynamic params){
-
print(params);
-
}
主函数中我们调用printDynamicParams函数:
-
main(List<String> arguments) {
-
printDynamicParams(12.33);
-
printDynamicParams('liyahong');
-
printDynamicParams("Dart Method test");
-
printDynamicParams(10);
-
printDynamicParams(true);
-
}
控制台输出结果:
这里我们可以传入任意类型,适用于参数类型不固定的情况使用。这里大家可能会有一个疑惑,包括我当时学习的时候也有这个疑惑,既然dynamic、var、Object都可以指定任意类型,那它们有什么区别吗?下面我们就来说下这个问题。
(1)var
var是C# 3中引入的,其实它仅仅只是一个语法. var本身并不是一种类型, 其它两者object和dynamic是类型。var声明的变量在赋值的那一刻,就已经决定了它是什么类型。
如果你这样使用,就会有编译错误:
-
var a = 1;
-
a = "Test";
(2)Object
object之所以能够被赋值为任意类型的原因,其实都知道,因为所有的类型都派生自object.
它可以赋值为任何类型:
-
object a = 1;
-
a = "Test";
(3)dynamic
dynamic不是在编译时候确定实际类型的, 而是在运行时。
所以下面的代码是能够通过编译的,但是会在运行时报错:
-
dynamic a = "test";
-
a++;
2.不指定返回值类型的函数
-
/**
-
* 我们可以不指定返回值类型,这样的函数返回值默认为Object,也就是说你可以返回任意类型
-
* params: 可以是任意类型
-
*/
-
printReturnObjectParams(Object params){
-
print(params);
-
return params;
-
}
-
printObjectParams(Object params){
-
print(params);
-
}
主函数中我们调用printReturnObjectParams 和 printObjectParams函数:
-
main(List<String> arguments) {
-
print(printReturnObjectParams("liyahong"));
-
print(printReturnObjectParams(111));
-
print(printReturnObjectParams(12.36));
-
print(printObjectParams(true));
-
printObjectParams('test');
-
}
控制台输出结果:
由上面的结果可以看出,如果没有返回值得时候默认将会返回null。
3.如果你的函数中只有一个表达式,你可以使用快速写法
-
/**
-
* 无返回值类型函数的快速写法
-
* 注意:这种写法只适用于无返回值 并且 函数体中仅有一个表达式的函数。
-
*/
-
void printNumber(num number) => print(number);
主函数中我们调用printNumber函数:
-
printNumber(123);
-
printNumber(22.3333);
控制台输出结果:
这里我们提到了num关键字,在上篇博客中没有讲到,这里简单说一下。
我们先看一下官方对它的说法:
-
/**
-
* An integer or floating-point number.
-
* It is a compile-time error for any type other than [int] or [double]
-
* to attempt to extend or implement num.
-
*/
-
翻译:
-
/**
-
* 整数或浮点数。
-
* 除[int]或[double]之外的任何类型都是编译时错误
-
* 试图扩展或实现num。
-
*/
也就是说它是一个数值类型,仅支持int 和 double类型。
4.可选参数
一个函数可以有两种参数:可选的和必需的,必需参数放在前面,后面跟可选参数
可选参数可以是位置参数或命名参数,两种都可以有默认值,如果没有提供默认值则为null
(1)可选的命名参数
定义一个函数,使用 {param1, param2, …} 指定命名参数,调用函数时,你可以指定使用命名参数 paramName: value
无默认值例子:
-
/**
-
* 没有默认值
-
*/
-
void printBool({bool flag, bool action}) => print("flag: " + flag.toString() + "\r\naction: " + action.toString() + "\r\n");
有默认值(命名参数使用“:”指定默认值)例子:
-
/**
-
* 有默认值
-
*/
-
void printDefaultBool({bool flag: false}) => print(flag);
主函数中我们调用printBool 和 printDefaultBool函数:
-
main(List<String> arguments) {
-
printBool(flag: true, action: false);
-
printBool(flag: false);
-
printBool();
-
printDefaultBool(flag: true);
-
printDefaultBool();
-
}
控制台输出结果:
(2)可选的位置参数
把参数用 [ ] 包装起来,就能标识成位置参数
无默认值例子:
-
/**
-
* 可选的位置参数
-
* 无默认值
-
*/
-
String msg(String msg, [String time]){
-
if (time != null) {
-
return msg + ' with ' + time;
-
}
-
return msg;
-
}
有默认值(位置参数使用“=”指定默认值)例子:
-
/**
-
* 可选的位置参数
-
* 有默认值
-
*/
-
String msgTwo(String msg, [String time = '2018', String name]){
-
if (time == null) {
-
return msg + " from " + name;
-
}
-
if (name != null) {
-
return msg + " with " + time + " from " + name;
-
}
-
return msg + " with " + time;
-
}
主函数中我们调用msg 和 msgTwo函数:
-
print(msg("This is msg content", '2017'));
-
print(msg("Tiis is msg content"));
-
print(msgTwo("This is msgTwo content", '2017', 'liyahong'));
-
print(msgTwo("This is msgTwo content", null, 'liyahong'));
-
print(msgTwo("This is msgTwo content"));
控制台输出结果:
总结:可选的命名参数的声明使用“{}”,使用“:”指定默认值,可选的位置函数的声明使用“[]”,使用“=”指定默认值。
6.关于重载
Dart语言是不支持方法重载的。这里可能会有人问:“Dart不支持方法重载,那构造函数怎么办呢?”,虽然Dart它不支持方法的重载,但是它支持命名构造函数,我们通过下面例子学习一下:
-
class Test{
-
int x;
-
int y;
-
Test(){}
-
Test.X(int x){
-
this.x = x;
-
}
-
Test.Y(int y){
-
this.y = y;
-
}
-
Test.XY(int x, int y){
-
this.x = x;
-
this.y = y;
-
}
-
@override
-
String toString() {
-
if (x != null && y != null) {
-
return "x: " + x.toString() + " y: " + y.toString();
-
}
-
if (x != null) {
-
return "x: " + x.toString();
-
}
-
if (y != null) {
-
return "y: " + y.toString();
-
}
-
return super.toString();
-
}
-
}
我们在主函数中创建Test对象:
-
main(List<String> arguments) {
-
Test testX = new Test.X(1);
-
print(testX.toString());
-
Test testY = new Test.Y(2);
-
print(testY.toString());
-
Test testXY = new Test.XY(3, 4);
-
print(testXY.toString());
-
}
控制台输出结果:
具体内容我们后面讲解。
7.高级函数
-
/**
-
* 高级函数
-
* element 没有指定参数类型,默认Object任何类型
-
*/
-
printElement(element){
-
print(element);
-
}
在主函数中调用printElement函数,这里是将函数作为参数传入
-
main(List<String> arguments) {
-
var list = ['张三', '李四', '王麻子'];
-
list.forEach(printElement);
-
}
控制台输出结果:
将一个函数分配给一个变量
-
main(List<String> arguments) {
-
var loudify = (msg) => '${msg.toUpperCase()}';
-
print(loudify('hello'));
-
}
控制台输出结果:
8.作用域
dart的作用域跟其他语言一样,直接看一个例子
-
var test = true;
-
main(List<String> arguments) {
-
var test1 = true;
-
myFunction(){
-
var test2 = true;
-
needFunction(){
-
var test3 = true;
-
assert(test);
-
assert(test1);
-
assert(test2);
-
assert(test3);
-
}
-
}
-
}
9.闭包
dart的闭包就是函数对象,其实跟JavaScript的闭包函数差不多,理论请参考JavaScript的闭包函数,这里直接写个例子
-
//返回一个函数对象,功能是返回累加的数字
-
Function makeAdder(num addBy) {
-
return (num i) => addBy + i;
-
}
-
main(List<String> arguments) {
-
//创建一个函数add2,add2返回2
-
var add2 = makeAdder(2);
-
//创建一个函数add4,add4返回4
-
var add4 = makeAdder(4);
-
//add2返回2+3
-
assert(add2(3) == 5);
-
//add4返回4+3
-
assert(add4(3) == 7);
-
}
10.函数是否相等
测试高阶函数、静态方法和实例方法是否相等
-
//一个高阶函数
-
foo() {}
-
class SomeClass {
-
//一个静态方法
-
static void bar() {}
-
//一个实例方法
-
void baz() {}
-
}
-
main(List<String> arguments) {
-
var x;
-
//比较高阶函数
-
x = foo;
-
assert(foo == x);
-
//比较静态方法
-
x = SomeClass.bar;
-
assert(SomeClass.bar == x);
-
//比较实例方法
-
var v = new SomeClass();
-
var w = new SomeClass();
-
var y = w;
-
x = w.baz;
-
assert(y.baz == x);
-
assert(v.baz != w.baz);
-
}
参考:Dart基础-函数:https://blog.csdn.net/hekaiyou/article/details/46639683
var,Object,dynamic的区别:https://blog.csdn.net/mrobama/article/details/53812898