Dart 是一个真正的面向对象语言,方法也是对象并且具有一种 类型 Function
。 这意味着,方法可以赋值给变量,也可以当做其他方法的参数。可以把方法当做参数调用另外一个方法
- 一等方法对象
int function(int m, int n) {
return m + n;
}
//类型可省略(不推荐)
function2(m, n) {
return m + n;
}
//对于只有一个表达式的方法,可以选择使用缩写语法来定义:
add(m, n) => m + n;
- 可选位置参数
dart定义了参数位置可选,应无需像java一样重载那么多构造函数;
//使用[]表示参数位置可选
void function4([int m, int n]) {
}
function4(1);
function4(1,2);//若需要传值给n,则必须保证m也传值
- 可选命名参数
//使用{}表示参数需要命名
void function5({int s,int k}){
}
function5(8);//报错
function5(k:67);//正确
- 匿名方法
没有名字的方法,称之为匿名方法,也可以称之为 lambda 或者 closure 闭包。匿名方法的声明为:
([Type] param1, …) {
codeBlock;
};
如:
var list = [12, 4, 12, 223, 3];
list.forEach((i) {
print(i);
});
- 异常
Java 不同的是,所有的 Dart 异常是非检查异常。 方法不一定声明了他们所抛出的异常, 并且不要求你捕获任何异常。
Dart 提供了 Exception
和Error
类型, 以及一些子类型。你还 可以定义自己的异常类型。但是, Dart 代码可以 抛出任何非 null 对象为异常,不仅仅是实现了 Exception
或者Error
的对象。
try {
List<int> ll = [1, 2];
List<int> l = const [1, 2, 34];
l.add(23); //报错,不可修改的变量
const List<int> dd = [12, 1, 232];
dd.add(232); //报错,不可修改的变量
throw 2324;
} on int catch (e) { //捕获指定int类型异常
print(e);
} catch (e, s) {
print(e);
} finally {};
- 类与构造函数
由于把构造函数参数赋值给实例变量的场景太常见了, Dart 提供了一个语法糖来简化这个操作:
class Example {
num a;
num b;
Example(this.a, this.b);
// Example(this.b); // 错误 不允许重载
Example.b(this.b){ //方便识别方法名称 //命名构造函数
// a = 0;
}
//重定向构造函数
//一个重定向构造函数是没有代码的,在构造函数声明后,使用 冒号调用其他构造函数。
Example.ab(num a, int b) :this(a, b); //调用上面的构造函数
}
- 常量构造函数
如果你的类提供一个状态不变的对象,你可以把这些对象 定义为编译时常量。要实现这个功能,需要定义一个 const
构造函数, 并且声明所有类的变量为
class Sing {
final num m;
final num k;
const Sing(this.m, this.k);
}
使用const传递相同的变量的表示的是同一变量 占用同一内存
sing = const Sing(12, 23);
sing2 = const Sing(12, 23); //
print(sing == sing2); //为true
- 工厂构造函数实现单例
当实现一个使用factory
关键词修饰的构造函数时,这个构造函数不必创建类的新实例
class Manager {
static Manager _manager; //下划线是只能在库内调用,相当于java的私有
//和static是一样的, 区别是factory毕竟是构造函数,需要返回一个实例,而static是静态方法。
factory Manager.geIntance(){
//因为是单线程,无需加锁synchronized
if (_manager == null) {
_manager = new Manager._init();
}
return _manager;
}
Manager._init(); //改步骤相当于java中的 private构造方法,防止外部创建实例
}
- 可覆写的操作符
把已经定义的、有一定功能的操作符进行重新定义。可以重新定义的操作符有:
< | + | | | [] |
---|---|---|---|
> | / | ^ | []= |
<= | ~/ | & | ~ |
>= | * | << | == |
– | % | >> |
比如:List就重写了 []
。
class Minue {
num m;
num n;
Minue operator -(Minue mine) {
return Minue(m - mine.m, mine.n - mine.n);
}
Minue(this.m, this.n);
}
void main() {
var minue = Minue(2, 2);
var minue2 = minue - Minue(3, 3);
print(minue.m);
print(minue2.m);
}
- 抽象类
使用 abstract
修饰符定义一个抽象类。抽象类中允许出现无方法体的方法
abstract class Parent {
String name;
void printName(); //抽象方法,不需要在方法前声明 abstract
}
抽象类不能被实例化,除非定义工厂方法并返回子类。
abstract class Parent {
String name;
//默认构造方法
Parent(this.name);
//工厂方法返回Child实例
factory Parent.test(String name){
return new Child(name);
}
void printName();
}
// extends 继承抽象类
class Child extends Parent{
Child(String name) : super(name);
@override
void printName() {
print(name);
}
}
void main() {
var p = Parent.test("Lance");
print(p.runtimeType); //输出实际类型 Child
p.printName();
}
- 接口
与Java不同,Dart中没有interface
关键字,Dart中每个类都隐式的定义了一个包含所有实例成员的接口, 并且这个类实现了这个接口。如果你想 创建类 A 来支持 类 B 的 方法,而不想继承 B 的实现, 则类 A 应该实现 B 的接口。
class Listener{
void success(){}
void fail(){}
}
class ExapmleListener implements Listener{
@override
void fail() {
// TODO: implement fail
}
@override
void success() {
// TODO: implement success
}
}
与继承的区别在于:
1、单继承,多实现。
2、继承可以有选择的重写父类方法并且可以使用super
,实现强制重新定义接口所有成员。
- 可调用的类
如果 Dart 类实现了 test()
函数则 可以当做方法来调用。
class Name {
test(String a, String b) => '$a $b!';
}
void main() {
var name = new Name();
var str = name.test("we", "ds");
print(str);
}
- 混合mixins
class A {
name() {
print("A");
}
}
class B {
name() {
print("B");
}
}
class C with A,B
{}
void main() {
var c = new C();
c.name(); //C输出值为B,从右侧检索
}