flutter开发之——Dart中的函数

前言

Dart是一个真正的面向对象语言,方法也是对象并且具有一种类型Function。 这意味着,方法可以赋值给变量,也可以当做其他方法的参数。 也可以把Dart类的实例当做方法来调用。大家可以通过阅读lambda表达式与Kotlin高阶函数与Kotlin中的函数类似对比学习。首先通过hello world了解一下Dart中的函数:

_printHello("白瑞德");
void _printHello(String name) {
  print("hello: ${name}");
}
>>> hello: 白瑞德

注意:Dart没有public、protected、private的概念。但是如果变量或函数以下划线_开始,则该函数或变量属于这个包私有(private)的方法。

函数的定义

函数定义指定特定任务的执行方式。在使用函数之前,必须先定义它。dart中函数的定义和Java中的类似。由函数入参、返回结果类型和函数体组成

String function_name(String parma) { 
   //statements 
}

void function_name(String parma) { 
   //statements 
}

function_name(parma) { 
   //statements 
   return 2;
}

其中void关键字表示该函数不向滴啊用这返回任何值,可以省略不写。函数的入参也可以忽略参数类型,这样函数默认接受dynamic类型的参数,也就是任何类型都可以传递。当省略了返回值类型的时候,也会默认返回值的类型为dynamic
注意:dynamic类型可能会带来运行时异常:

_printInt(int name) {
  return "Hello";
}

_printInt(_printInt(2))

这段代码会报:type 'String' is not a subtype of type 'int'
注意:上述三个function_name是不可以出现在同一个代码块里,有Java开发经验的一定知道这种形式就是Java函数的重载,但这在Dart里是行不通的,Dart里有其他方式实现这种重载。
对于只有一个表达式的方法,可以选择使用缩写语法来定义:
String function_name(name) => name+name;
函数体只能是一个表达式,不能使用语句(if-else)

可选参数

Dart中没有类似Java重载的函那样的函数,我们可以使用可选参数来实现类似的功能。
可选参数可以是命名参数或者基于位置的参数,但是这两种参数不能同时当做可选参数。

可选命名参数

调用方法的时候,你可以使用这种形式paramName: value来指定命名参数。一个函数可以同时拥有可选参数和必选参数,但是必选参数必须在最前面
例如:

_printInt(age: 19,address: "粤海街道");
_printHello("白瑞德",age: 19);
_printInt({int age,String address}) {
  ...
}
_printHello(name,{int age,String address}) {
  ...
}

在可选参数的时候,可以使用=来定义可选参数的默认值。默认值只能是编译时常量。如果没有提供默认值,则默认值为null。

//年龄默认为7,而address默认为null
_printHello(name,{int age = 7,String address}) {
    ...
}

可选位置参数

把一些方法的参数放到[]中就变成可选位置参数了:

_printString("白瑞德");
_printString([String name,int age = 7,String address]){
      ...
}

可选的命名参数的声明使用“{}”,使用“:”指定默认值,可选的位置函数的声明使用“[]”,使用“=”指定默认值。

重载与构造方法

Dart语言是同名函数的,即使入参不同。那么问题就来了,构造函数怎么办?难道只能一个构造函数吗?答案是否定的。
Dare支持命名构造函数,使用命名构造函数可以为一个类实现多个构造函数, 或者使用命名构造函数来更清晰的表明你的意图:

class User {
  String name;
  User.init();
  User.initName(name){
    this.name = name;
  }
}

注意:构造函数不能继承,所以超类的命名构造函数 也不会被继承。如果你希望 子类也有超类一样的命名构造函数, 你必须在子类中自己实现该构造函数。
默认情况下,子类的构造函数会自动调用超类的无名无参数的默认构造函数。 超类的构造函数在子类构造函数体开始执行的位置调用。如果提供了一个 initializer list(初始化参数列表),则初始化参数列表在超类构造函数执行之前执行。 下面是构造函数执行顺序:

  • initializer list(初始化参数列表)
  • superclass’s no-arg constructor(超类的无名构造函数)
  • main class’s no-arg constructor(主类的无名构造函数)

如果超类没有无名无参数构造函数,则你需要手工的调用超类的其他构造函数。在构造函数参数后使用冒号 (:) 可以调用 超类构造函数。
由于超类构造函数的参数在构造函数执行之前执行,所以参数可以是一个表达式或者一个方法调用:

class Student extends User{
  Student.init() : super.init();
  Student.initName(name):super.initName(name){
  }
}

一等方法对象

在Dart中,有一种函数被称为:Functions as first-class objects一等方法对象。可一把方法当做参数调用另外一个方法,也可以把方法赋值给一个变量。

printElement(element) {
  print(element);
}
var list = [1, 2, 3];
list.forEach(printElement);

var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';
assert(loudify('hello') == '!!! HELLO !!!');

lambda/匿名函数/闭包

大部分方法都带有名字。也可以创建没有名字的方法,称之为匿名方法,有时候也被称为Lambda或者闭包,这是一种表示函数的简介方式。可以把匿名方法赋值给一个变量。

var printName =(num){
    print(num);
    return num;
};
//当只有一行表达式时,可以使用箭头函数
var printName =(num) => print(num);

一个闭包是一个方法对象,不管该对象在何处被调用,该对象都可以访问其作用域内的变量。方法可以封闭定义到其作用域内的变量。下面的示例中,makeAdder()捕获到了变量addBy。不管你在那里执行makeAdder() 所返回的函数,都可以使用addBy参数。

Function makeAdder(num addBy) {
  return (num i) => addBy + i;
}

main() {
  // Create a function that adds 2.
  var add2 = makeAdder(2);

  // Create a function that adds 4.
  var add4 = makeAdder(4);

  assert(add2(3) == 5);
  assert(add4(3) == 7);
}

结语

Dart中的函数使用基本讲解完毕了,想要进一步了解的可以去官方教程上学习

你可能感兴趣的:(flutter开发之——Dart中的函数)