Dart 語言了解


Dart 語言了解

概念

當您了解Dart語言時,請記住以下事實和概念:

  • 您可以放在變量中的所有內容都是一個對象,每個對象都是一個類的實例。偶數,函數和 null對象。所有對象都從Object類繼承。

  • 盡管Dart是強類型的,但類型注釋是可選的,因為Dart可以推斷類型。在上面的代碼中,number 推斷為類型int。如果要明確說明不需要任何類型,請 使用特殊類型dynamic。

  • Dart支持泛型類型,如List<int>(整數列表)或List<dynamic>(任何類型的對象列表)。

  • Dart支持頂級函數(例如main()),以及綁定到類或對象的函數(分別是靜態和實例方法)。您還可以在函數內創建函數(嵌套函數或本地函數)。

  • 類似地,Dart支持頂級變量,以及綁定到類或對象的變量(靜態和實例變量)。實例變量有時稱為字段或屬性。

  • 與Java,飛鏢不具備關鍵字public,protected和private。如果標識符以下划線(_)開頭,則它對其庫是私有的。有關詳細信息,請參閱 庫和可見性。

  • 標識符可以以字母或下划線(_)開頭,后跟這些字符加數字的任意組合。

  • Dart有兩個表達式(具有運行時值)和 語句(不具有)。例如,條件表達式 condition ? expr1 : expr2的值為expr1或expr2。將其與if-else語句進行比較,該語句沒有任何值。語句通常包含一個或多個表達式,但表達式不能直接包含語句。

  • Dart工具可以報告兩種問題:警告和錯誤。警告只是表明您的代碼可能無法正常工作,但它們不會阻止您的程序執行。錯誤可以是編譯時或運行時。編譯時錯誤會阻止代碼執行; 運行時錯誤導致 代碼執行時引發異常。

變量

這是創建變量並初始化它的示例:

var name = 'Bob';

變量存儲引用。調用的變量name包含對String值為“Bob” 的對象的引用。

name推斷變量的類型String,但您可以通過指定它來更改該類型。如果對象不限於單一類型,請按照設計指南指定Object或dynamic類型。

dynamic name = 'Bob' ;

另一種選擇是顯式聲明可以推斷出的類型:

String name = 'Bob' ;

默認值

未初始化的變量的初始值為null。即使是帶有數字類型的變量最初也是null,因為數字也都是對象。

int lineCount ; assert (lineCount == null );

最終和常數

如果您從不打算更改變量,請使用final或const代替var或替代類型。最終變量只能設置一次; const變量是編譯時常量。

以下是創建和設置最終變量的示例:

final name = 'Bob' ; //沒有類型注釋
final String nickname = 'Bobby' ;  

使用const為您要為變量的編譯時間常數。如果const變量在類級別,請標記它static const。在聲明變量的地方,將值設置為編譯時常量,例如數字或字符串文字,const變量或常數上的算術運算結果:

const bar = 1000000; // Unit of pressure (dynes/cm2)
const double atm = 1.01325 * bar; // Standard atmosphere 

內置類型

  • numbers 數字
  • strings 字符串
  • booleans 布爾
  • lists 列表(也稱為數組)
  • maps 映射
  • runes 符文(用於表示字符串中的Unicode字符)
  • symbols 符號

數字

兩種形式:

int
整數值不大於64位,具體取決於平台。

double
64位(雙精度)浮點數,由IEEE 754標准規定。

字符串

Dart字符串是一系列UTF-16代碼單元。您可以使用單引號或雙引號來創建字符串:

var s1 = 'Single quotes work well for string literals.';
var s2 = "Double quotes work just as well.";
var s3 = 'It\'s easy to escape the string delimiter.';
var s4 = "It's even easier to use the other delimiter.";

布爾

類型bool。只有兩個對象具有bool類型:true和false,它們都是編譯時常量。

// Check for an empty string.
var fullName = '';
assert(fullName.isEmpty);

// Check for zero.
var hitPoints = 0;
assert(hitPoints <= 0);

// Check for null.
var unicorn;
assert(unicorn == null);

// Check for NaN.
var iMeantToDoThis = 0 / 0;
assert(iMeantToDoThis.isNaN);

Lists

也許幾乎每種編程語言中最常見的集合是數組或有序的對象組。在Dart中,數組是 List對象,因此大多數人只是將它們稱為列表。

var list = [1, 2, 3];
assert(list.length == 3);
assert(list[1] == 2);

list[1] = 1;
assert(list[1] == 1);

Maps

通常,映射是關聯鍵和值的對象。鍵和值都可以是任何類型的對象。每個鍵只出現一次,但您可以多次使用相同的值。

var gifts = {
  // Key:    Value
  'first': 'partridge',
  'second': 'turtledoves',
  'fifth': 'golden rings'
};

var nobleGases = {
  2: 'helium',
  10: 'neon',
  18: 'argon',
};

Runes

在Dart中,符文是字符串的UTF-32代碼點。

Unicode為世界上所有書寫系統中使用的每個字母,數字和符號定義唯一的數值。由於Dart字符串是一系列UTF-16代碼單元,因此在字符串中表示32位Unicode值需要特殊語法。

main() {
  var clapping = '\u{1f44f}';
  print(clapping);
  print(clapping.codeUnits);
  print(clapping.runes.toList());

  Runes input = new Runes(
      '\u2665  \u{1f605}  \u{1f60e}  \u{1f47b}  \u{1f596}  \u{1f44d}');
  print(new String.fromCharCodes(input));
}

Symbols

符號對象表示達特程序聲明的操作者或標識符。您可能永遠不需要使用符號,但它們對於按名稱引用標識符的API非常有用,因為縮小會更改標識符名稱而不會更改標識符符號。

要獲取標識符的符號,請使用符號文字, #后面跟着標識符:

#radix
#bar

符號文字是編譯時常量。

功能

Dart是一種真正的面向對象語言,因此即使是函數也是對象並且具有類型Function。 這意味着函數可以分配給變量或作為參數傳遞給其他函數。您也可以像調用函數一樣調用Dart類的實例。

以下是實現函數的示例:

bool isNoble(int atomicNumber) {
  return _nobleGases[atomicNumber] != null;
}

bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;

main()函數

每個應用程序都必須具有頂級main()功能,該功能用作應用程序的入口點。該main()函數返回void並具有List 參數的可選參數。

以下main()是Web應用程序的功能示例:

void main() {
  querySelector('#sample_text_id')
    ..text = 'Click me!'
    ..onClick.listen(reverseText);
}

注意:..前面代碼中 的語法稱為級聯。使用級聯,您可以對單個對象的成員執行多個操作。

作為第一類對象的函數

您可以將函數作為參數傳遞給另一個函數。例如:

void printElement(int element) {
  print(element);
}

var list = [1, 2, 3];

// Pass printElement as a parameter.
list.forEach(printElement);

控制流程語句

您可以使用以下任一方法控制Dart代碼的流程:

if 和 else
for 循環
while 和 do-while 循環
break 和 continue
switch 和 case
assert
也可以使用 try-catch 和影響控制流 throw,如異常中所述。

示例


if (isRaining()) {
  you.bringRainCoat();
} else if (isSnowing()) {
  you.wearJacket();
} else {
  car.putTopDown();
}

var message = StringBuffer('Dart is fun');
for (var i = 0; i < 5; i++) {
  message.write('!');
}

while (!isDone()) {
  doSomething();
}
do {
  printLine();
} while (!atEndOfPage());

var command = 'OPEN';
switch (command) {
  case 'CLOSED':
    executeClosed();
    break;
  case 'PENDING':
    executePending();
    break;
  case 'APPROVED':
    executeApproved();
    break;
  case 'DENIED':
    executeDenied();
    break;
  case 'OPEN':
    executeOpen();
    break;
  default:
    executeUnknown();
}

try {
  breedMoreLlamas();
} catch (e) {
  print('Error: $e'); // Handle the exception first.
} finally {
  cleanLlamaStalls(); // Then clean up.
}

Dart是一種面向對象的語言,具有類和基於mixin的繼承。每個對象都是一個類的實例,所有類都來自Object。 基於Mixin的繼承意味着雖然每個類(除了Object)只有一個超類,但是類體可以在多個類層次結構中重用。

class Point {
  num x; // Declare instance variable x, initially null.
  num y; // Declare y, initially null.
  num z = 0; // Declare z, initially 0.

  Point(num x, num y) {
    // There's a better way to do this, stay tuned.
    this.x = x;
    this.y = y;
  }

  num distanceTo(Point other) {
    var dx = x - other.x;
    var dy = y - other.y;
    return sqrt(dx * dx + dy * dy);
  }

  class Rectangle {
        num left, top, width, height;

        Rectangle(this.left, this.top, this.width, this.height);

        // Define two calculated properties: right and bottom.
        num get right => left + width;
        set right(num value) => left = value - width;
        num get bottom => top + height;
        set bottom(num value) => top = value - height;
    }
}

抽象類和方法

抽象方法
實例,getter和setter方法可以是抽象的,定義一個接口,但將其實現留給其他類。抽象方法只能存在於抽象類中。

抽象類
使用abstract修飾符定義抽象類 - 無法實例化的類。抽象類對於定義接口非常有用,通常還有一些實現。如果希望抽象類看起來是可實例化的,請定義工廠構造函數。

abstract class Doer {
  // Define instance variables and methods...

  void doSomething(); // Define an abstract method.
}

class EffectiveDoer extends Doer {
  void doSomething() {
    // Provide an implementation, so the method is not abstract here...
  }
}

繼承和實現

實現:

// A person. The implicit interface contains greet().
class Person {
  // In the interface, but visible only in this library.
  final _name;

  // Not in the interface, since this is a constructor.
  Person(this._name);

  // In the interface.
  String greet(String who) => 'Hello, $who. I am $_name.';
}

// An implementation of the Person interface.
class Impostor implements Person {
  get _name => '';

  String greet(String who) => 'Hi $who. Do you know who I am?';
}

String greetBob(Person person) => person.greet('Bob');

void main() {
  print(greetBob(Person('Kathy')));
  print(greetBob(Impostor()));
}

繼承:

class Television {
  void turnOn() {
    _illuminateDisplay();
    _activateIrSensor();
  }
  // ···
}

class SmartTelevision extends Television {
  void turnOn() {
    super.turnOn();
    _bootNetworkInterface();
    _initializeMemory();
    _upgradeApps();
  }
  // ···
}

重寫:

class SmartTelevision extends Television {
  @override
  void turnOn() {...}
  // ···
}

枚舉類型

枚舉類型(通常稱為枚舉或枚舉)是一種特殊類,用於表示固定數量的常量值。

使用枚舉
使用enum關鍵字聲明枚舉類型:

enum Color { red, green, blue }

靜態類變量和方法

使用static關鍵字實現類范圍的變量和方法。

靜態變量:

class Queue {
  static const initialCapacity = 16;
  // ···
}

void main() {
  assert(Queue.initialCapacity == 16);
}

靜態方法:

import 'dart:math';

class Point {
  num x, y;
  Point(this.x, this.y);

  static num distanceBetween(Point a, Point b) {
    var dx = a.x - b.x;
    var dy = a.y - b.y;
    return sqrt(dx * dx + dy * dy);
  }
}

void main() {
  var a = Point(2, 2);
  var b = Point(4, 4);
  var distance = Point.distanceBetween(a, b);
  assert(2.8 < distance && distance < 2.9);
  print(distance);
}

泛型

如果您查看基本數組類型的API文檔 List,您會看到該類型實際上是List 。<...>表示法將List標記為 通用(或參數化)類型 - 具有正式類型參數的類型。按照慣例,大多數類型變量都有單字母名稱,例如E,T,S,K和V.

var names = <String>['Seth', 'Kathy', 'Lars'];
var pages = <String, String>{
  'index.html': 'Homepage',
  'robots.txt': 'Hints for web robots',
  'humans.txt': 'We are people, not machines'
};

使用庫

使用import指定如何從一個庫中的命名空間在另一個庫的范圍內使用。

唯一需要的參數import是指定庫的URI。對於內置庫,URI具有特殊dart:方案。對於其他庫,您可以使用文件系統路徑或package: 方案。該package:方案指定由包管理器(如pub工具)提供的庫。

import 'dart:html';
import 'package:test/test.dart';
import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;

異步支持

Dart庫中包含許多返回Future或Stream對象的函數。這些函數是異步的:它們在設置可能耗時的操作(例如I/O)后返回,而不等待該操作完成。

處理Future

當您需要完成的Future的結果時,您有兩個選擇:

  • 使用async和await。
  • 使用Future API。

使用async和await異步的代碼,但它看起來很像同步代碼。

await lookUpVersion();
Future checkVersion() async {
  var version = await lookUpVersion();
  // Do something with version
}

使用try,catch和finally 處理使用await以下代碼的錯誤和清理:

try {
  version = await lookUpVersion();
} catch (e) {
  // React to inability to look up the version
}

聲明異步函數

一個異步函數是一個函數體標有async修改。
將async關鍵字添加到函數使其返回Future。

Future<String> lookUpVersion() async => '1.0.0';

如果您的函數沒有返回有用的值,請設置其返回類型Future<void>

處理Streams

當您需要從Stream獲取值時,您有兩個選擇:

  • 使用async和異步for循環(await for)。
  • 使用Stream API。

注意: 在使用之前await for,請確保它使代碼更清晰,並且您確實希望等待所有流的結果。

await for (varOrType identifier in expression) {
  // Executes each time the stream emits a value.
}

Generators

當您需要延遲地生成一系列值時,請考慮使用生成器函數。Dart內置支持兩種形式:

  • 同步生成器:返回一個Iterable對象。
  • 異步生成器:返回Stream對象。

要實現同步生成器函數,請將函數體標記為sync,並使用yield語句來傳遞值。
要實現異步生成器函數,請將函數體標記為async
,並使用yield語句來傳遞值。

Iterable<int> naturalsTo(int n) sync* {
  int k = 0;
  while (k < n) yield k++;
}

Stream<int> asynchronousNaturalsTo(int n) async* {
  int k = 0;
  while (k < n) yield k++;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM