因要学习flutter平台,平台语言使用Dart,看了一下官方的demo:
https://github.com/flutter/flutter
看起来有点吃力,还是学习Dart语言也有利于以后开发,学习地址:
https://www.dartlang.org/guides/language/language-tour
https://www.dartlang.org/guides/libraries/library-tour
总结如下:
1.Dart简介
强类型语言
一个单线程的语言
类型注释是可选的,Dart可以推断类型。
Dart支持泛型类型
程序都必须具有顶级main()功能,该功能用作应用程序的入口点
接口可以有函数
类和接口是统一的,都是接口
2.关键字:
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 |
external 2 |
is |
sync 1 |
break |
extends |
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 |
- 带有上标1单词是上下文关键字,仅在特定位置具有含义。他们到处都是有效的标识符。
- 带有上标2单词是内置标识符。为了简化将JavaScript代码移植到Dart的任务,这些关键字在大多数地方都是有效的标识符,但它们不能用作类或类型名称,也不能用作导入前缀。
- 带有上标3的单词是与Dart 1.0发布后添加的异步支持相关的更新,有限的保留字。
3.变量与常量
3.1变量
var name = ‘Bob’ ; // 官方建议使用var
dynamic name = ‘Bob’ ;
String name = ‘Bob’ ;
未初始化的变量的初始值为null
不具备关键字public,protected和private。如果标识符以下划线(_)开头,则表示是私有的。
3.2常量
final name = ‘Bob’ ;//
const name = ‘Bob’ ;//
const在类级别,要加static const
const构造两个相同的编译时常量会产生同一个的实例
var a = const ImmutablePoint(1, 1);
var b = const ImmutablePoint(1, 1);
assert(identical(a, b)); // They are the same instance!
注:使用static关键字实现类范围的变量和方法( 对于常用或广泛使用的实用程序和功能,请考虑使用顶级函数而不是静态方法)。
区别一:final 要求变量只能初始化一次,并不要求赋的值一定是编译时常量,可以是常量也可以不是。而 const 要求在声明时初始化,并且赋值必需为编译时常量。
编译时常量:字面量(如数字、bool、字符串、List的字面量形式)、其它常量 或者 常量的算术运算,也可以是这些的组合形式(递归要求),简单地说常量就是可以在编译时确定的值。
区别二:final 是惰性初始化,即在运行时第一次使用前才初始化。而 const 是在编译时就确定值了。
区别三:const 可以修饰变量,也可以修饰值(value)。而 final 只用来修饰变量。
4.内置类型
4.1 数字
int: 整数值不大于64位,具体取决于平台。在Dart VM上,值可以是-2 63到2 63 – 1.编译为JavaScript的Dart使用 从-2 53到2 53 – 1的值。
double :64位(双精度)浮点数,由IEEE 754标准规定。
// 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’);
4.2 Strings(字符串)
Dart字符串是一系列UTF-16代码单元。您可以使用单引号或双引号来创建字符串。
var s1 = ‘Single ”quotes work well for‘ + ” string literals.”;
var s2 = “$s1“+‘case: ${s.toUpperCase()}‘;
可以想到”转义”只有’和”,使用三重引号进行“转义”:
var s1 = ”’
You can create”’
“””multi-line strings like this one.
“””;
4.3 Booleans
使用bool定义: bool b = true;
4.4数组
在Dart中的数组,其值可以是不同类型
var list = [“aa”,”dd”,3,newText(“test”)];
list.forEach((item) => print(‘I drink $item‘));
4.5 Maps
key或values要同一个类型(key可以是对象)
var gifts = {‘first’: ‘partridge’};
gifts[‘fourth’] = ‘calling birds’; // Add a key-value pair
gifts[“2”] = “222”;
print(gifts[“2”]); //打印
putIfAbsent()当且仅当键中的键尚不存在时,如果要为键指定值,请使用此方法
,您必须提供一个返回值的函数:
var teamAssignments = {};
teamAssignments.putIfAbsent(
‘Catcher’, () => pickToughestKid());
assert(teamAssignments[‘Catcher’] != null);
map循环:
gifts.forEach((k, v) {
print(‘I want to visit $k and swim at $v’);
// I want to visit first and swim at partridge
});
4.6 Runes
在Dart中,Runes是UTF-32位字符串。
Unicode为世界上所有书写系统中使用的每个字母,数字和符号定义唯一的数值。由于Dart字符串是一系列UTF-16位,因此在字符串中表示32位Unicode值需要特殊语法。
表达Unicode代码点的常用方法是 \uXXXX,其中XXXX是4位十六进制值。例如,心脏角色(♥)是\u2665。要指定多于或少于4个十六进制数字,请将值放在大括号中。例如,笑表情符号(😆)是\u{1f600}。
该字符串 类有几个属性,你可以用它来提取符文信息。在codeUnitAt和codeUnit属性返回16位编码单元。
以下示例说明了符文,16位代码单元和32位代码点之间的关系。
var clapping = ‘\u{1f44f}’;
print(clapping);
print(clapping.codeUnits); // [55357, 56399]
print(clapping.runes.toList()); //[128079]
Runes input = new Runes(‘\u2665 \u{1f605} \u{1f60e} \u{1f47b} \u{1f596} \u{1f44d}’);
print(new String.fromCharCodes(input)); // ♥ 😅 😎 👻 🖖 👍
4.7 URL
1.进行编码和解码的字符除了那些在URI特殊含义(例如/,:,&,#),使用encodeFull()和decodeFull()方法:
var uri = ‘http://example.org/api?foo=some message’;var encoded = Uri.encodeFull(uri);
assert(encoded ==
‘http://example.org/api?foo=some%20message‘);
2.编码和解码所有这一切都在一个URI特殊的含义,使用encodeComponent()和decodeComponent()方法:
var uri = ‘http://example.org/api?foo=some message’;
var encoded = Uri.encodeComponent(uri);
assert(encoded ==
‘http%3A%2F%2Fexample.org%2Fapi%3Ffoo%3Dsome%20message’);
3.组装与拆分:
var uri = Uri(
scheme: ‘http’,
host: ‘example.org’,
path: ‘/foo/bar’,
fragment: ‘frag’);
// var uri = Uri.parse(‘http://example.org:8080/foo/bar#frag’);
assert(uri.scheme == ‘http’);
assert(uri.host == ‘example.org’);
assert(uri.path == ‘/foo/bar’);
assert(uri.fragment == ‘frag’);
assert(uri.origin == ‘http://example.org:8080‘);
4.8 日期和时间
// Get the current date and time.
var now = DateTime.now();
// Create a new DateTime with the local time zone.
var y2k = DateTime(2000); // January 1, 2000
// Specify the month and day.
y2k = DateTime(2000, 1, 2); // January 2, 2000
// Specify the date as a UTC time.
y2k = DateTime.utc(2000); // 1/1/2000, UTC
// Specify a date and time in ms since the Unix epoch.
y2k = DateTime.fromMillisecondsSinceEpoch(946684800000,
isUtc: true);
// millisecondsSinceEpoch日期的属性返回自“Unix epoch” – 1970年1月1日UTC以来的毫秒数:
// Parse an ISO 8601 date.
y2k = DateTime.parse(‘2000-01-01T00:00:00Z’);
使用Duration类计算两个日期之间的差异并向前或向后移动日期(要使用UTC日期):
var y2k = DateTime.utc(2000);
// Add one year.
var y2001 = y2k.add(Duration(days: 366));
assert(y2001.year == 2001);
// Subtract 30 days.
var december2000 = y2001.subtract(Duration(days: 30));
assert(december2000.year == 2000);
assert(december2000.month == 12);
// Calculate the difference between two dates.
// Returns a Duration object.
var duration = y2001.difference(y2k);
assert(duration.inDays == 366); // y2k was a leap year.
5.函数
所有函数都返回一个值。如果未指定返回值,则将语句return null;隐式附加到函数体。
实现函数的示例:
bool isNoble (int atomicNumber ){
return _nobleGases [ atomicNumber ] != null ; }
虽然Effective Dart建议 为公共API键入注释,但如果省略类型,该函数仍然有效:
isNoble (atomicNumber ){ return _nobleGases [
atomicNumber ] != null ; }
对于只包含一个表达式的函数,可以使用简写语法:
bool isNoble (int atomicNumber )=>
_nobleGases [ atomicNumber ] != null ;
该语法是一个速记 。有时将表示法称为箭头语法。=> expr{ return expr; }=>
注意: 只有表达式 – 不是语句 – 可以出现在箭头(=>)和分号(;)之间。例如,您不能在其中放置if语句,但可以使用条件表达式。
定义必传参<child>、参数默认值<number>、选传参<device>:
bool isNoble (@required Widget child, int number = 1, [String device]){
return _nobleGases [ atomicNumber ] != null ; }
可以将函数作为参数传递给另一个函数:
void printElement(int element) {
print(element);
}
var list = [1, 2, 3];
// Pass printElement as a parameter.
list.forEach(printElement);
匿名函数:
var list = [‘apples’, ‘bananas’, ‘oranges’];
list.forEach((item) {
print(‘${list.indexOf(item)}: $item’);
});
再如:
button.onClick.listen((e) => window.alert(‘Confirmed!’));
嵌套函数:
void myFunction() {
var insideFunction = true;
void nestedFunction() {
var insideNestedFunction = true;
assert(insideFunction);
assert(insideNestedFunction);
}
}
变量函数:
在Dart中,可以把一个函数当一个变量:
/// 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);
var add5 = makeAdder(4);
assert(add2(3) == 5);
assert(add4(3) == 7);
// 函数变量一样可以比较
print(add4 == add5); // false 匿名函数都是新的
var adder = makeAdder;
print(adder== makeAdder); // true 函数同一个
// 函数变量可以理解为函数别名
print(adder(3)(7)); // 10
}
6.运算符
类型转换运算符:
操作者 |
含义 |
as |
类型转换 |
is |
如果对象具有指定的类型,则为True |
is! |
如果对象具有指定的类型,则返回false |
() |
表示函数调用 |
[] |
引用列表中指定索引处的值 |
. |
指表达式的属性; 示例:从表达式中foo.bar选择属性barfoo |
?. |
比如.最左边的操作数可以为null; 示例:从表达式中foo?.bar选择属性bar,foo非null(值为foo.bar),为null(值为null) |
.runtimeType |
获取对象的类型,可以使用Object的runtimeType属性,该属性返回一个Type对象,比如.print (‘a的类型是$ {a.runtimeType}’ ); |
obj is T如果obj实现指定的接口,则结果为true T。例如,obj is Object总是如此。
级联符号(..)
var sb = StringBuffer();
sb.write(‘foo’)
..write(‘bar’);
严格来说,级联的“双点”符号不是运算符。它只是Dart语法的一部分。
控制流程语句
您可以使用以下任一方法控制Dart代码的流程:
- if 和 else
- for 循环
- while和do– while循环
- break 和 continue
- switch 和 case
- Assert(布尔条件为false,则使用语句来中断正常执行,注:Flutter在调试模式下启用断言。)
您也可以使用try-catch和影响控制流throw
try {
// ···
} on Exception catch (e) {
print(‘Exception details:\n $e’);
} catch (e, s) { // 指定一个或两个参数catch()。第一个是抛出的异常,第二个是堆栈跟踪
print(‘Exception details:\n $e’);
print(‘Stack trace:\n $s’);
}finally {
print(‘finally‘);
}
其他运算符与java、C++、swift、OC语言一致,不一一列示了
7.类
class Musician extends Performer with Musical
with关键字后跟一个或多个mixin名称(类),声明没有构造函数,并且没有调用super
7.1构造函数
1.如果您未声明构造函数,则会为您提供默认构造函数。默认构造函数没有参数,并在超类中调用无参数构造函数。
2.子类不从其父类继承构造函数。声明没有构造函数的子类只有默认(无参数,无名称)构造函数。
3.超类没有未命名的无参数构造函数,则必须手动调用超类中的一个构造函数。在冒号(:)之后,在构造函数体(如果有)之前指定超类构造函数。
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;
}
}
同样:
class Point {
num x, y;
// Syntactic sugar for setting x and y
// before the constructor body runs.
Point(this.x, this.y);
// Named constructor
Point.origin() { // 默认构制方法时调用
x = 0;
y = 0;
}
}
7.2重定向构造函数
有时构造函数的唯一目的是重定向到同一个类中的另一个构造函数。重定向构造函数的主体是空的,构造函数调用出现在冒号(:)之后。
class Point {
num x, y;
// The main constructor for this class.
Point(this.x, this.y);
// Delegates to the main constructor.
Point.alongXAxis(num x) : this(x, 0);
}
7.3常量构造函数
如果您的类生成永远不会更改的对象,则可以使这些对象成为编译时常量。为此,请定义const构造函数并确保所有实例变量都是final。(应该是单例的意思)
class ImmutablePoint {
static final ImmutablePoint origin =
const ImmutablePoint(0, 0);
final num x, y;
const ImmutablePoint(this.x, this.y);
}
7.4 工厂构造函数
factory在实现不总是创建其类的新实例的构造函数时使用关键字。例如,工厂构造函数可能从缓存中返回实例,或者它可能返回子类型的实例。
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) { // 工厂构造函数无权访问this
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);
}
}
7.5重载运算符函数
您可以覆盖下表中显示的运算符。例如,如果定义Vector类,则可以定义+添加两个向量的方法。
< |
+ |
| |
[] |
> |
/ |
^ |
[]= |
<= |
~/ |
& |
~ |
>= |
* |
<< |
== |
– |
% |
>> |
|
注意:您可能已经注意到,这!=不是一个可覆盖的运算符。表达e1 != e2只是语法糖!(e1 == e2)。
例:
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));
}
7.6 哈希码 (hashCode)
class Person {
final String firstName, lastName;
Person(this.firstName, this.lastName);
// Override hashCode using strategy from Effective Java,
// Chapter 11.
@override
int get hashCode {
int result = 17;
result = 37 * result + firstName.hashCode;
result = 37 * result + lastName.hashCode;
return result;
}
// You should generally implement operator == if you
// override hashCode.
@override
bool operator ==(dynamic other) {
if (other is! Person) return false;
Person person = other;
return (person.firstName == firstName &&
person.lastName == lastName);
}
}