这里开始讲Dart语法中最重要的元素之一:方法,Dart里面的方法跟java还是有很大的不同
方法
Dart是一种真正的面向对象语言,因此即使是函数也是对象并且具有类型Function。
这意味着函数可以分配给变量或作为参数传递给其他函数。
您也可以像调用函数一样调用Dart类的实例。
bool isNoble(int atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
这是一个标准的方法,其中返回类型是可以省略的,Dart会自动推断,而它下面的那个方法则是一个方法的简写版
- 可选参数和必选参数
函数可以有两种类型的参数:必需和可选。首先列出所需参数,然后列出任何可选参数。命名的可选参数也可以标记为@required。当我们调用一个方法的时候,我们可以给方法填上一个默认值,例如:
//这是一个可选参数的的方法
optionalFunction({int a = 1 ,int b =2}){
return a+b;
}
//在调用的时候我可以选择传一个参数,也可以选择不传
main(){
optionalFunction(a:4);
optionalFunction(a:4,b:1);
optionalFunction(4,1);//TODO 错误!!!!
optionalFunction();
}
注意,这个方法在调用的时候不能像kotlin一样通过参数的顺序来指定参数,可选参数的方法传参必须在前面加上方法的参数名,来指定参数的值
如果我在可选参数前面加上@Required注解,就表明在这一群可选参数中,这个参数是必传项,不去传递这个参数是非法的
optionalFunction({int a = 1 ,@required int b }){
return a+b;
}
optionalFunction(a:4); //非法。必须传递b的值
注意:@Required 注解需要导入外部包才能使用
可以直接导入包:meta / meta.dart,也可以导入另一个导出meta的包,例如Flutter的包:flutter / material.dart。
- 可选位置参数
可选位置参数的意思就是即使你不传入这个参数,也可以调用这个方法,在上面一个例子中我们发现
optionalFunction({int a = 1 ,int b =3 }){
return a+b;
}
这个方法,如果调用的时候是这样调用的
optionalFunction(4);
这样编译是过不了的,系统不知道你这个4是a还是b
但是可选参数中这样调用是可以的,即使你这个可选参数没有默认值,看代码
String say(String from, String msg, [String device]) {
var result = '$from says $msg';
if (device != null) {
result = '$result with a $device';
}
return result;
}
assert(say('Bob', 'Howdy') == 'Bob says Howdy');
assert(say('Bob', 'Howdy', 'smoke signal') ==
'Bob says Howdy with a smoke signal');
在上面这个示例中,第三个参数device在第一次调用中是没有传递的,但是编译器没有报错,这就是可选位置参数与全部可选参数的区别
级联表示法
级联类似于java里面的build设计模式,可以通过单行一系列的语法操作一个对象
class Grammar2 {
var x, y, z;
}
var g2 = Grammar2();
g2 ..x = 1 ..y = 2..z=3;//这样就完成了一系列的赋值
等价于
g2.x = 1; g2.y=2;g2.z=3;
querySelector('#sample_text_id')
..text = 'Click me!'
..onClick.listen(reverseText);
Functions as first-class objects(这个感觉翻译成中文怪怪的)
你可以传递一个方法当作一个参数传递给另一个方法
void printElement(int element) {
print(element);
}
var list = [1, 2, 3];
// Pass printElement as a parameter.
list.forEach(printElement);
上面这是一个简单版本的方法传递,这里延伸一下方法传递的概念Typedefs,java里面是没有方法当作参数的概念的,Dart将这个玩的很6,我们看看Typedefs
Typedefs
在Dart中,函数是对象,就像string和int一样,typedef或为函数类型提供了在声明字段和返回类型时可以使用的名称。当函数类型分配给变量时,typedef会保留类型信息。
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);
}
上面这种是普通的方法传递的代码,就跟注释上面的疑问一样,都知道这个传递进来的f是一个方法,但是是什么类型的方法呢?
这个时候typedef就派上用场了将f分配给比较时,类型信息会丢失。f的类型是(Object,Object)→int(其中→表示返回),但比较的类型是Function。
如果我们将代码更改为使用显式名称并保留类型信息,则开发人员和工具都可以使用该信息。
typedef Compare = int Function(Object a, Object b); //typedef关键字需要定义在class的外围
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 = int Function(T a, T b);
int sort(int a, int b) => a - b;
void main() {
assert(sort is Compare); // True!
}
方法的注解
Dart常用的有@override和@deprecated意思跟java一样,这里略过
匿名方法
也称作为无名方法,顾名思义,就是这个方法没有方法名,其他的跟普通方法一样。举个例子:如果我们初始化一个值ax,这个ax的值需要从一个方法的返回值中拿到,在java里面我们这么做
int ax = getAx(9);
int getAx(int a){
return a *2;
}
Dart中是这样的
var ax = (a) => a2;
是不是简洁了很多?那么无名方法在哪里呢?就是这个(a)=>a2这个方法除了没有名字,其他跟上面的一样
第二个应用场景就是有些方法需要你传递一个方法进去,第一种办法是上面我们例子说的,定义一个普通方法传递进去
int sort(Object a, Object b) {
......
}
functionPass(sort); //普通方法
//无名的写法是这样的
void functionPass((Object a, Object b){
.......
})
//更加常用的地方的是
var list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
print('${list.indexOf(item)}: $item');
});
方法的返回值
这里单独提一下方法的返回值,默认情况下dart的方法不写返回值不代表没有返回值,他的返回值是null
foo() {}
assert(foo() == null);
未完待续~~~~~