flutter 使用的dart 语言学习
任何开发都离不开开发语言,而flutter使用的是dart 语言。磨刀不误砍柴功,因此我们先简单的学习下dart语言,让我们看官方demo 更简单些。
dart 基本编码
void main() {
var number = 32;
printInterger(number);
}
printInterger(int aNumber){
print("The number is $aNumber");
}
- 注释
dart 注释使用 //
例如
// This is a comment.
多行注释使用 /**/
- 基本类型
dart 自身带有的数据类型有
numbers
strings
booleans
lists (also known as arrays)
sets
maps
runes (for expressing Unicode characters in a string)
symbols
numbers 的类型有 int ,double,
Strings 用单引号和双引号引起了的是字符串
booleans 的值是 true false
lists 表示 []
sets 用 {} 例如var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'};
maps 也是{} 表示,但是{}的写法不同
var gifts = {
// Key: Value
'first': 'partridge',
'second': 'turtledoves',
'fifth': 'golden rings'
};
Runes 这个UTF-32 编码,相当于 unicode编码吧
获取变量{expression})
dart 关键词
abstract 2 | dynamic 2 | implements 2 | show 1 |
as 2 | else | import 2 | static 2 |
assert | enum | in | super |
async 1 | export 2 | interface 2 | switch |
await 3 | extends | is | sync 1 |
break | external 2 | library 2 | this |
case | factory 2 | mixin 2 | throw |
catch | false | new | true |
class | final | null | try |
const | finally | on 1 | typedef 2 |
continue | for | operator 2 | var |
covariant 2 | Function 2 | part 2 | void |
default | get 2 | rethrow | while |
deferred 2 | hide 1 | return | with |
do | if | set 2 | yield 3 |
对象引用
var name = 'Bob';
这只是对一个对象的引用references。
如果对象是动态变化的,那么我们应该这样写
dynamic name = 'Bob';
如果我们明确知道对象的类型可以这样写
String name = 'Bob';
默认值
没有初始化的对象的默认值都是null。
image.png这里注意即使,number 对象。默认值也是null,而不是0。因为number 也是对象
常量我们用Final 和 const
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
要是改变 用Final 标记的变量 ,编译器报错
这里需要注意 const 是编译期间的常量
重点编译期间
字符串和number 转换
// String -> int
var one = int.parse('1');
assert(one == 1);
// String -> double
var onePointOne = double.parse('1.1');
assert(onePointOne == 1.1);
// int -> String
String oneAsString = 1.toString();
assert(oneAsString == '1');
// double -> String
String piAsString = 3.14159.toStringAsFixed(2);
assert(piAsString == '3.14');
位操作
assert((3 << 1) == 6); // 0011 << 1 == 0110
assert((3 >> 1) == 1); // 0011 >> 1 == 0001
assert((3 | 4) == 7); // 0011 | 0100 == 0111
-
右移动
- << 左移动
- | or
- & and
字符串连接
字符串连接是通过+ 来操作的
字符串的写法距离
var s1 = 'String '
'concatenation'
" works even over line breaks.";
var s2 = 'The + operator ' + 'works, as well.';
var s1 = '''
You can create
multi-line strings like this one.
''';
var s2 = """This is also a
multi-line string.""";
创建"raw" 字符串
image.png字符串前面通过r来标记
const 常量表示法,这里不是很理解。需要用的时候测试
// These work in a const string.
const aConstNum = 0;
const aConstBool = true;
const aConstString = 'a constant string';
// These do NOT work in a const string.
var aNum = 0;
var aBool = true;
var aString = 'a string';
const aConstList = [1, 2, 3];
const validConstString = '$aConstNum $aConstBool $aConstString';
// const invalidConstString = '$aNum $aBool $aString $aConstList';
Lists
var list = [1, 2, 3];
assert(list.length == 3);
assert(list[1] == 2);
list[1] = 1;
assert(list[1] == 1);
不可变lists
var constantList = const [1, 2, 3];
Sets
空集合
var names = <String>{};
var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'};
集合操作,加入一个元素或者集合
var elements = <String>{};
elements.add('fluorine');
elements.addAll(halogens);
不可变集合
final constantSet = const {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'};
Maps
var gifts = {
// Key: Value
'first': 'partridge',
'second': 'turtledoves',
'fifth': 'golden rings'
};
key 可以是数字
var nobleGases = {
2: 'helium',
10: 'neon',
18: 'argon',
};
var gifts = Map();
gifts['first'] = 'partridge';
gifts['second'] = 'turtledoves';
gifts['fifth'] = 'golden rings';
var nobleGases = Map();
nobleGases[2] = 'helium';
nobleGases[10] = 'neon';
nobleGases[18] = 'argon';
final constantMap = const {
2: 'helium',
10: 'neon',
18: 'argon',
};
函数
函数的标准写法
bool isNoble(int atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
dart 具有推理能力这样的也是对的
isNoble(atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
要是函数只有一个表达式
我们可以这样写
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
=> expr 相当于 {return expr;}
函数的可选参数
多参数函数写法
void enableFlags({bool bold, bool hidden}) {...}
调用
enableFlags(bold: true, hidden: false);
函数必须传入参数
const Scrollbar({Key key, @required Widget child})
可选参数写法
String say(String from, String msg, [String device]) {
var result = '$from says $msg';
if (device != null) {
result = '$result with a $device';
}
return result;
}
函数参数的默认值
/// Sets the [bold] and [hidden] flags ...
void enableFlags({bool bold = false, bool hidden = false}) {...}
// bold will be true; hidden will be false.
enableFlags(bold: true);
有默认值就可以不传值了。使用默认值
多个可选参数
String say(String from, String msg,
[String device = 'carrier pigeon', String mood]) {
var result = '$from says $msg';
if (device != null) {
result = '$result with a $device';
}
if (mood != null) {
result = '$result (in a $mood mood)';
}
return result;
}
assert(say('Bob', 'Howdy') ==
'Bob says Howdy with a carrier pigeon');
list 和map 作为默认值
void doStuff(
{List<int> list = const [1, 2, 3],
Map<String, String> gifts = const {
'first': 'paper',
'second': 'cotton',
'third': 'leather'
}}) {
print('list: $list');
print('gifts: $gifts');
}
函数作为参数
void printElement(int element) {
print(element);
}
var list = [1, 2, 3];
// Pass printElement as a parameter.
list.forEach(printElement);
函数指针作为变量
var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';
assert(loudify('hello') == '!!! HELLO !!!');
匿名函数
匿名函数写法
([[Type] param1[, …]]) {
codeBlock;
};
匿名函数举例
var list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
print('${list.indexOf(item)}: $item');
});
变量作用域
bool topLevel = true;
void main() {
var insideMain = true;
void myFunction() {
var insideFunction = true;
void nestedFunction() {
var insideNestedFunction = true;
assert(topLevel);
assert(insideMain);
assert(insideFunction);
assert(insideNestedFunction);
}
}
}
函数内是可以包含函数的
闭包
/// Returns a function that adds [addBy] to the
/// function's argument.
Function makeAdder(num addBy) {
return (num i) => addBy + i;
}
void 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);
}
函数相等的判断
void foo() {} // A top-level function
class A {
static void bar() {} // A static method
void baz() {} // An instance method
}
void main() {
var x;
// Comparing top-level functions.
x = foo;
assert(foo == x);
// Comparing static methods.
x = A.bar;
assert(A.bar == x);
// Comparing instance methods.
var v = A(); // Instance #1 of A
var w = A(); // Instance #2 of A
var y = w;
x = w.baz;
// These closures refer to the same instance (#2),
// so they're equal.
assert(y.baz == x);
// These closures refer to different instances,
// so they're unequal.
assert(v.baz != w.baz);
}
返回值
所有函数都必须有一个返回值,没有return的默认是返回的null
foo() {}
assert(foo() == null);
操作符
Description | Operator | ||
---|---|---|---|
unary postfix | expr++ expr-- () [] . ?. | ||
unary prefix | -expr !expr ~expr ++expr --expr | ||
multiplicative | * / % ~/ | ||
additive | + - | ||
shift | << >> | ||
bitwise AND | & | ||
bitwise XOR | ^ | ||
bitwise OR | ` | ` | |
relational and type test | >= > <= < as is is! | ||
equality | == != | ||
logical AND | && | ||
logical OR | ` | ` | |
if null | ?? | ||
conditional | expr1 ? expr2 : expr3 | ||
cascade | .. | ||
assignment | = *= /= ~/= %= += -= <<= >>= &= ^= | = ??= |
举例
a++
a + b
a = b
a == b
c ? a : b
a is T
计算操作符
Operator | Meaning |
---|---|
+ | Add |
– | Subtract |
-expr | Unary minus, also known as negation (reverse the sign of the expression) |
* | Multiply |
/ | Divide |
~/ | Divide, returning an integer result |
% | Get the remainder of an integer division (modulo) |
Operator | Meaning |
---|---|
as |
Typecast (also used to specify library prefixes) 强制类型转换 |
is |
这里判断对象是否是类型使用的,是返回true |
is! |
False if the object has the specified type |
if (emp is Person) {
// Type check
emp.firstName = 'Bob';
}
(emp as Person).firstName = 'Bob';
条件表达式
condition ? expr1 : expr2 判断条件成立执行expr1,否则执行expr2
expr1 ?? expr2 判断expr1返回不是null,那么就返回expr1 执行结果,否则执行expr2。
String playerName(String name) => name ?? 'Guest';
// Slightly longer version uses ?: operator.
String playerName(String name) => name != null ? name : 'Guest';
// Very long version uses if-else statement.
String playerName(String name) {
if (name != null) {
return name;
} else {
return 'Guest';
}
}
级联表示法 (..)
querySelector('#confirm') // Get an object.
..text = 'Confirm' // Use its members.
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));
正常写法
var button = querySelector('#confirm');
button.text = 'Confirm';
button.classes.add('important');
button.onClick.listen((e) => window.alert('Confirmed!'));
final addressBook = (AddressBookBuilder()
..name = 'jenny'
..email = 'jenny@example.com'
..phone = (PhoneNumberBuilder()
..number = '415-555-0100'
..label = 'home')
.build())
.build();
看着可以实现链式调用
Operator | Name | Meaning |
---|---|---|
() | Function application | Represents a function call |
[] | List access | Refers to the value at the specified index in the list |
. | Member access | Refers to a property of an expression; example: foo.bar selects property bar from expression foo |
?. | Conditional member access | Like ., but the leftmost operand can be null; example: foo?.bar selects property bar from expression foo unless foo is null (in which case the value of foo?.bar is null) |
流程控制
- if and else
- for loops
- while and do-while loops
- break and continue
- switch and case
- assert
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('!');
}
闭包对对象的捕获
var callbacks = [];
for (var i = 0; i < 2; i++) {
callbacks.add(() => print(i));
}
callbacks.forEach((c) => c());
candidates.forEach((candidate) => candidate.interview());
while (!isDone()) {
doSomething();
}
do {
printLine();
} while (!atEndOfPage());
while (true) {
if (shutDownRequested()) break;
processIncomingRequests();
}
for (int i = 0; i < candidates.length; i++) {
var candidate = candidates[i];
if (candidate.yearsExperience < 5) {
continue;
}
candidate.interview();
}
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();
}
switch 可以自己定义字符串
var command = 'CLOSED';
switch (command) {
case 'CLOSED':
executeClosed();
continue nowClosed;
// Continues executing at the nowClosed label.
nowClosed:
case 'NOW_CLOSED':
// Runs for both CLOSED and NOW_CLOSED.
executeNowClosed();
break;
}
// Make sure the variable has a non-null value.
assert(text != null);
// Make sure the value is less than 100.
assert(number < 100);
// Make sure this is an https URL.
assert(urlString.startsWith('https'));
异常捕获
throw FormatException('Expected at least 1 section');
throw 'Out of llamas!';
try {
breedMoreLlamas();
} on OutOfLlamasException {
// A specific exception
buyMoreLlamas();
} on Exception catch (e) {
// Anything else that is an exception
print('Unknown exception: $e');
} catch (e) {
// No specified type, handles all
print('Something really unknown: $e');
对象
使用对象成员语法
var p = Point(2, 2);
// Set the value of the instance variable y.
p.y = 3;
// Get the value of y.
assert(p.y == 3);
// Invoke distanceTo() on p.
num distance = p.distanceTo(Point(4, 4));
我们可以使用?.来避免使用exception
p?.y = 4;
通过constructors 来生成对象
var p1 = Point(2, 2);
var p2 = Point.fromJson({'x': 1, 'y': 2});
创建编译期间的对象
var p = const ImmutablePoint(2, 2);
const pointAndLine = const {
'point': const [const ImmutablePoint(0, 0)],
'line': const [const ImmutablePoint(1, 10), const ImmutablePoint(-2, 11)],
};
const pointAndLine = {
'point': [ImmutablePoint(0, 0)],
'line': [ImmutablePoint(1, 10), ImmutablePoint(-2, 11)],
};
该对象只创建一次,相当于单例么
对象变量设置默认值
class Point {
num x; // Declare instance variable x, initially null.
num y; // Declare y, initially null.
num z = 0; // Declare z, initially 0.
}
没有实例化的变量都是null
Constructors 写法
class Point {
num x, y;
Point(num x, num y) {
// There's a better way to do this, stay tuned.
this.x = x;
this.y = y;
}
}
this 指向当前实例
对象都是默认的实例方法。
初始化方法是不能继承的
对象名字就是实例化方法
自定义实例化方法,
class Point {
num x, y;
Point(this.x, this.y);
// Named constructor
Point.origin() {
x = 0;
y = 0;
}
}
自定义实例化方法,我们就必须加入默认的实例化方法 Point(this.x, this.y);
对象的继承
class Person {
String firstName;
Person.fromJson(Map data) {
print('in Person');
}
}
class Employee extends Person {
// Person does not have a default constructor;
// you must call super.fromJson(data).
Employee.fromJson(Map data) : super.fromJson(data) {
print('in Employee');
}
}
main() {
var emp = new Employee.fromJson({});
// Prints:
// in Person
// in Employee
if (emp is Person) {
// Type check
emp.firstName = 'Bob';
}
(emp as Person).firstName = 'Bob';
}
这里需要注意了
打印结果是
in Person
in Employee
先调用父类方法,在调用子类的方法
对象的成员变量的初始化
// Initializer list sets instance variables before
// the constructor body runs.
Point.fromJson(Map<String, num> json)
: x = json['x'],
y = json['y'] {
print('In Point.fromJson(): ($x, $y)');
}
有点c++的写法
import 'dart:math';
class Point {
final num x;
final num y;
final num distanceFromOrigin;
Point(x, y)
: x = x,
y = y,
distanceFromOrigin = sqrt(x * x + y * y);
}
main() {
var p = new Point(2, 3);
print(p.distanceFromOrigin);
}
常量初始化。
class ImmutablePoint {
static final ImmutablePoint origin =
const
(0, 0);
final num x, y;
const ImmutablePoint(this.x, this.y);
}
用类方法的形式生成对象
class Logger {
final String name;
bool mute = false;
// _cache is library-private, thanks to
// the _ in front of its name.
static final Map<String, Logger> _cache =
<String, Logger>{};
factory Logger(String name) {
if (_cache.containsKey(name)) {
return _cache[name];
} else {
final logger = Logger._internal(name);
_cache[name] = logger;
return logger;
}
}
Logger._internal(this.name);
void log(String msg) {
if (!mute) print(msg);
}
}
factory 相当于ios的类方法,而成员变量标记static相当于类成员变量
对象方法
import 'dart:math';
class Point {
num x, y;
Point(this.x, this.y);
num distanceTo(Point other) {
var dx = x - other.x;
var dy = y - other.y;
return sqrt(dx * dx + dy * dy);
}
}
getter 和setter 方法
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;
}
void main() {
var rect = Rectangle(3, 4, 20, 15);
assert(rect.left == 3);
rect.right = 12;
assert(rect.left == -8);
}
虚方法和类 相当于协议
这里很像java
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();
}
// ···
}
操作符的覆盖
< + | []
> / ^ []=
<= ~/ & ~
>= * << ==
– % >>
dart可以覆盖操作符
class Vector {
final int x, y;
Vector(this.x, this.y);
Vector operator +(Vector v) => Vector(x + v.x, y + v.y);
Vector operator -(Vector v) => Vector(x - v.x, y - v.y);
// Operator == and hashCode not shown. For details, see note below.
// ···
}
void main() {
final v = Vector(2, 3);
final w = Vector(2, 2);
assert(v + w == Vector(4, 5));
assert(v - w == Vector(0, 1));
}
noSuchMethod()
当我们尝试使用不存在的方法和变量的时候,会调用到noSuchMethod()方法中,我们可以通过覆盖noSuchMethod()方法来捕获调用
class A {
// Unless you override noSuchMethod, using a
// non-existent member results in a NoSuchMethodError.
@override
void noSuchMethod(Invocation invocation) {
print('You tried to use a non-existent member: ' +
'${invocation.memberName}');
}
}
枚举
enum Color { red, green, blue }
每一个枚举值都一个int值与之对应
assert(Color.red.index == 0);
assert(Color.green.index == 1);
assert(Color.blue.index == 2);
枚举使用
List<Color> colors = Color.values;
assert(colors[2] == Color.blue);
var aColor = Color.blue;
switch (aColor) {
case Color.red:
print('Red as roses!');
break;
case Color.green:
print('Green as grass!');
break;
default: // Without this, you see a WARNING.
print(aColor); // 'Color.blue'
}
mixins
用法
class Musician extends Performer with Musical {
// ···
}
class Maestro extends Person
with Musical, Aggressive, Demented {
Maestro(String maestroName) {
name = maestroName;
canConduct = true;
}
}
最小的mixin
mixin Musical {
bool canPlayPiano = false;
bool canCompose = false;
bool canConduct = false;
void entertainMe() {
if (canPlayPiano) {
print('Playing piano');
} else if (canConduct) {
print('Waving hands');
} else {
print('Humming to self');
}
}
}
继承关系
mixin MusicalPerformer on Musician {
// ···
}
类变量和方法
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);
}
泛型
var names = List<String>();
names.addAll(['Seth', 'Kathy', 'Lars']);
names.add(42); // Error
abstract class ObjectCache {
Object getByKey(String key);
void setByKey(String key, Object value);
}
abstract class StringCache {
String getByKey(String key);
void setByKey(String key, String value);
}
abstract class Cache<T> {
T getByKey(String key);
void setByKey(String key, T value);
}
var names = <String>['Seth', 'Kathy', 'Lars'];
var uniqueNames = <String>{'Seth', 'Kathy', 'Lars'};
var pages = <String, String>{
'index.html': 'Homepage',
'robots.txt': 'Hints for web robots',
'humans.txt': 'We are people, not machines'
};
class SomeBaseClass{
}
class Extender extends SomeBaseClass {
}
class Foo<T extends SomeBaseClass> {
// Implementation goes here...
String toString() => "Instance of 'Foo<$T>'";
}
void main(){
var someBaseClassFoo = Foo<SomeBaseClass>();
var extenderFoo = Foo<Extender>();
print("${someBaseClassFoo.toString()}");
print("${ extenderFoo.toString()}");
;
}
generic method
T first<T>(List<T> ts) {
// Do some initial work or error checking, then...
T tmp = ts[0];
// Do some additional checking or processing...
return tmp;
}
返回值,参数,规定该类使用的类型都可以
使用libraries
import 'dart:html';
import 'package:test/test.dart';
库别名
import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;
// Uses Element from lib1.
Element element1 = Element();
// Uses Element from lib2.
lib2.Element element2 = lib2.Element();
引用库的一部分
// Import only foo.
import 'package:lib1/lib1.dart' show foo;
// Import all names EXCEPT foo.
import 'package:lib2/lib2.dart' hide foo;
懒加载库
import 'package:greetings/hello.dart' deferred as hello;
需要调用
Future greet() async {
await hello.loadLibrary();
hello.printGreeting();
}
await lookUpVersion();
使用await 必须在异步中,很重要
Future checkVersion() async {
var version = await lookUpVersion();
// Do something with version
}
Future main() async {
checkVersion();
print('In main: version is ${await lookUpVersion()}');
}
Future<String> lookUpVersion() async => '1.0.0';
Typedefs 的使用
class SortedCollection {
Function compare;
SortedCollection(int f(Object a, Object b)) {
compare = f;
}
}
// Initial, broken implementation.
int sort(Object a, Object b) => 0;
void main() {
SortedCollection coll = SortedCollection(sort);
// All we know is that compare is a function,
// but what type of function?
assert(coll.compare is Function);
}
typedef Compare = int Function(Object a, Object b);
class SortedCollection {
Compare compare;
SortedCollection(this.compare);
}
// Initial, broken implementation.
int sort(Object a, Object b) => 0;
void main() {
SortedCollection coll = SortedCollection(sort);
assert(coll.compare is Function);
assert(coll.compare is Compare);
}
typedef Compare<T> = int Function(T a, T b);
int sort(int a, int b) => a - b;
void main() {
assert(sort is Compare<int>); // True!
}
Metadata
class Television {
/// _Deprecated: Use [turnOn] instead._
@deprecated
void activate() {
turnOn();
}
/// Turns the TV's power on.
void turnOn() {...}
}
定义自己的元
library todo;
class Todo {
final String who;
final String what;
const Todo(this.who, this.what);
}
import 'todo.dart';
@Todo('seth', 'make this do something')
void doSomething() {
print('do something');
}