【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);
}

控制檯輸出結果:ide

 

這裏咱們能夠傳入任意類型,適用於參數類型不固定的狀況使用。這裏你們可能會有一個疑惑,包括我當時學習的時候也有這個疑惑,既然dynamic、var、Object均可以指定任意類型,那它們有什麼區別嗎?下面咱們就來講下這個問題。函數

  • (1)var

    var是C# 3中引入的,其實它僅僅只是一個語法. var自己並非一種類型, 其它二者object和dynamic是類型。var聲明的變量在賦值的那一刻,就已經決定了它是什麼類型。學習

    若是你這樣使用,就會有編譯錯誤:測試

    var a = 1;
    a = "Test";
  • (2)Object

    object之因此可以被賦值爲任意類型的緣由,其實都知道,由於全部的類型都派生自object. this

    它能夠賦值爲任何類型:spa

    object a = 1;
    a = "Test";
  • (3)dynamic

    dynamic不是在編譯時候肯定實際類型的, 而是在運行時。翻譯

    因此下面的代碼是可以經過編譯的,可是會在運行時報錯:3d

    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');
}

控制檯輸出結果:code

 

由上面的結果能夠看出,若是沒有返回值得時候默認將會返回null。

3.若是你的函數中只有一個表達式,你可使用快速寫法

/**
* 無返回值類型函數的快速寫法
* 注意:這種寫法只適用於無返回值 而且 函數體中僅有一個表達式的函數。
*/
void printNumber(num number) => print(number);

主函數中咱們調用printNumber函數:

main(List<String> arguments) {
  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"));

控制檯輸出結果:

 

總結:可選的命名參數的聲明使用「{}」,使用「:」指定默認值,可選的位置函數的聲明使用「[]」,使用「=」指定默認值。

5.關於重載

 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());
}

控制檯輸出結果:

 

具體內容咱們後面講解。

6.高級函數

/**
* 高級函數
* 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'));
}

控制檯輸出結果:

 

7.做用域

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);     }   } }

8.閉包

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);
}

9.函數是否相等

測試高階函數、靜態方法和實例方法是否相等

 

//一個高階函數
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);
}
相關文章
相關標籤/搜索