Flutter學習之Dart語法(二)

本文首發於我的博客html

函數

函數的基本定義

  • Dart是一種真正的面嚮對象語言,因此即便函數也是對象,全部也有類型, 類型就是Function。
  • 這也就意味着函數能夠做爲變量定義或者做爲其餘函數的參數或者返回值.

函數的定義方式:git

返回值 函數的名稱(參數列表) {
  函數體
  return 返回值
}
複製代碼

按照上面的定義方式, 咱們定義一個完整的函數:github

int sum(num num1, num num2) {
  return num1 + num2;
}
複製代碼

Effective Dart建議對公共的API, 使用類型註解, 可是若是咱們省略掉了類型, 依然是能夠正常工做的編程

sum(num1, num2) {
  return num1 + num2;
}
複製代碼

另外, 若是函數中只有一個表達式, 那麼可使用箭頭語法(arrow syntax)數組

  • 注意, 這裏面只能是一個表達式, 不能是一個語句
sum(num1, num2) => num1 + num2;

複製代碼

函數的參數問題

函數的參數能夠分紅兩類: 必須參數和可選參數 前面使用的參數都是必須參數.bash

可選參數

可選參數能夠分爲 命名可選參數 和 位置可選參數 定義方式:閉包

命名可選參數: {param1, param2, ...}
位置可選參數: [param1, param2, ...]

複製代碼

命名可選參數的演示:編程語言

// 命名可選參數
printInfo1(String name, {int age, double height}) {
  print('name=$name age=$age height=$height');
}

// 調用printInfo1函數
printInfo1('eagle'); // name=eagle age=null height=null
printInfo1('eagle', age: 18); // name=eagle age=18 height=null
printInfo1('eagle', age: 18, height: 1.88); // name=eagle age=18 height=1.88
printInfo1('eagle', height: 1.88); // name=eagle age=null height=1.88

複製代碼

位置可選參數的演示:函數

// 定義位置可選參數
printInfo2(String name, [int age, double height]) {
  print('name=$name age=$age height=$height');
}

// 調用printInfo2函數
printInfo2('eagle'); // name=eagle age=null height=null
printInfo2('eagle', 18); // name=eagle age=18 height=null
printInfo2('eagle', 18, 1.88); // name=eagle age=18 height=1.88

複製代碼

命名可選參數, 能夠指定某個參數是必傳的(使用@required, 有問題)ui

// 命名可選參數的必須
printInfo3(String name, {int age, double height, @required String address}) {
  print('name=$name age=$age height=$height address=$address');
}

複製代碼

參數默認值

參數能夠有默認值, 在不傳入的狀況下, 使用默認值

注意, 只有可選參數才能夠有默認值, 必須參數不能有默認值

// 參數的默認值
printInfo4(String name, {int age = 18, double height=1.88}) {
  print('name=$name age=$age height=$height');
}
複製代碼

Dart中的main函數就是一個接受可選的列表參數做爲參數的, 因此在使用main函數時, 咱們能夠傳入參數, 也能夠不傳入

函數是一等公民

在不少語言中, 函數並不能做爲一等公民來使用, 好比Java/OC. 這種限制讓編程不夠靈活, 因此現代的編程語言基本都支持函數做爲一等公民來使用, Dart也支持. 這就意味着你能夠將函數賦值給一個變量, 也能夠將函數做爲另一個函數的參數或者返回值來使用.

main(List<String> args) {
  // 1.將函數賦值給一個變量
  var bar = foo;
  print(bar);

  // 2.將函數做爲另外一個函數的參數
  test(foo);

  // 3.將函數做爲另外一個函數的返回值
  var func =getFunc();
  func('kobe');
}

// 1.定義一個函數
foo(String name) {
  print('傳入的name:$name');
}

// 2.將函數做爲另一個函數的參數
test(Function func) {
  func('eagle');
}

// 3.將函數做爲另外一個函數的返回值
getFunc() {
  return foo;
}

複製代碼

匿名函數的使用

大部分咱們定義的函數都會有本身的名字, 好比前面定義的foo、test函數等等。 可是某些狀況下,給函數命名太麻煩了,咱們可使用沒有名字的函數,這種函數能夠被稱之爲匿名函數( anonymous function),也能夠叫lambda或者closure。

main(List<String> args) {
  // 1.定義數組
  var movies = ['盜夢空間', '星際穿越', '少年派', '大話西遊'];

  // 2.使用forEach遍歷: 有名字的函數
  printElement(item) {
    print(item);
  }
  movies.forEach(printElement);

  // 3.使用forEach遍歷: 匿名函數
  movies.forEach((item) {
    print(item);
  });
  movies.forEach((item) => print(item));
}

複製代碼

詞法做用域

dart中的詞法有本身明確的做用域範圍,它是根據代碼的結構({})來決定做用域範圍的 優先使用本身做用域中的變量,若是沒有找到,則一層層向外查找。

var name = 'global';
main(List<String> args) {
  // var name = 'main';
  void foo() {
    // var name = 'foo';
    print(name);
  }

  foo();
}

複製代碼

詞法閉包

閉包能夠訪問其詞法範圍內的變量,即便函數在其餘地方被使用,也能夠正常的訪問。

main(List<String> args) {
  makeAdder(num addBy) {
    return (num i) {
      return i + addBy;
    };
  }

  var adder2 = makeAdder(2);
  print(adder2(10)); // 12
  print(adder2(6)); // 8

  var adder5 = makeAdder(5);
  print(adder5(10)); // 15
  print(adder5(6)); // 11
}

複製代碼

返回值問題

全部函數都返回一個值。若是沒有指定返回值,則語句返回null;隱式附加到函數體。

main(List<String> args) {
  print(foo()); // null
}

foo() {
  print('foo function');
}

複製代碼

運算符

除法、整除、取模運算

咱們來看一下除法、整除、取模運算

var num = 7;
print(num / 3); // 除法操做, 結果2.3333..
print(num ~/ 3); // 整除操做, 結果2;
print(num % 3); // 取模操做, 結果1;
複製代碼

??=賦值操做

dart有一個不少語言都不具有的賦值運算符:

  • 當變量爲null時,使用後面的內容進行賦值。
  • 當變量有值時,使用本身原來的值。
main(List<String> args) {
  var name1 = 'eagle';
  print(name1);
  // var name2 = 'kobe';
  var name2 = null;
  name2 ??= 'james'; 
  print(name2); // 當name2初始化爲kobe時,結果爲kobe,當初始化爲null時,賦值了james
}
複製代碼

條件運算符:

Dart中包含一直比較特殊的條件運算符:expr1 ?? expr2

  • 若是expr1是null,則返回expr2的結果;
  • 若是expr1不是null,直接使用expr1的結果。
var temp = 'eagle';
var temp = null;
var name = temp ?? 'kobe';
print(name);
複製代碼

級聯語法:..

  • 某些時候,咱們但願對一個對象進行連續的操做,這個時候可使用級聯語法
class Person {
  String name;

  void run() {
    print("${name} is running");
  }

  void eat() {
    print("${name} is eating");
  }

  void swim() {
    print("${name} is swimming");
  }
}

main(List<String> args) {
  final p1 = Person();
  p1.name = 'eagle';
  p1.run();
  p1.eat();
  p1.swim();

  final p2 = Person()
              ..name = "eagle"
              ..run()
              ..eat()
              ..swim();
}
複製代碼

流程控制

和大部分語言的特性比較類似,這裏就再也不詳細贅述,看一下便可。

if和else

和其餘語言用法同樣 這裏有一個注意點:不支持非空即真或者非0即真,必須有明確的bool類型

  • 咱們來看下面name爲null的判斷
var age = null;
if(age){ //錯誤的用法
   print(age);
}

複製代碼

循環操做

基本的for循環

for (var i = 0; i < 5; i++) {
  print(i);
}
複製代碼

for in遍歷List和Set類型

var names = ['eagle', 'kobe', 'curry'];
for (var name in names) {
  print(name);
}
複製代碼

while和do-while和其餘語言一致 break和continue用法也是一致

switch-case

普通的switch使用

注意:每個case語句,默認狀況下必須以一個break結尾

main(List<String> args) {
  var direction = 'east';
  switch (direction) {
    case 'east':
      print('東面');
      break;
    case 'south':
      print('南面');
      break;
    case 'west':
      print('西面');
      break;
    case 'north':
      print('北面');
      break;
    default:
      print('其餘方向');
  }
}
複製代碼
相關文章
相關標籤/搜索