编程语言虽然千差万别,但归根结底,它们的设计思想无非就是回答两个问题:

1、如何表示信息;

2、如何处理信息;

函数

函数是一段用来独立地完成某个功能的代码。函数是对象类型,它的类型叫做Function。这意味着函数也可以被定义为变量,甚至可以被定义为参数传递给另一个函数。
bool isZero(int number) => number == 0;
void printInfo(int number, Function check) => print("$number is Zero: ${check(number)}");
如果函数体只有一行表达式,就可以像JavaScript语言那样用箭头函数来简化这个函数

一个函数中可能需要传递多个参数。如何让这类函数的参数声明变得更加优雅、可维护,同时降低调用者的使用成本?

C++与Java的做法是,提供函数的重载,即提供同名但参数不同的函数。但Dart认为重载会导致混乱,因此从设计之初就不支持重载,而是提供了可选命名参数和可选参数。
bool isZero(int number) => number == 0;
void printInfo(int number, Function check) => print("$number is Zero: ${check(number)}"); // 要达到可选命名参数的用法,那就在定义函数的时候给参数加上{}
void enableFlagsA({bool bold, bool hidden}) => print("$bold, $hidden"); // 定义可选命名参数时增加默认值
void enableFlagesB({bool bold = true, bool hidden = false}) => print("$bold, $hidden"); // 可忽略的参数在函数定义时用[]符号指定
void enableFlagesC(bool bold, [bool hidden]) => print("$bold, $hidden"); // 定义可忽略参数时增加默认值
void enableFlagesD(bool bold, [bool hidden = false]) => print("$bold, $hidden");

类是特定类型的数据和方法的集合,也是创建对象的模版。

类的定义及初始化

Dart是面向对象的语言,每个对象都是一个类的实例,都继承自顶层类型Object。 Dart中并没有public、protected、private这些关键字,只要在声明变量与方法时,在前面加上_即可作为private方法使用,如果不加_,则默认为public。不过_的限制范围并不是类访问级别的,而是库访问级别。

class Point {

  num x, y;
static num factor = 0;
// 语法糖,等同于在函数体内:this.x = x; this.y = y;
Point(this.x, this.y);
void printInfo() => print('($x,$y)');
static void printZValue() => print('$factor');
}
有时候类的实例化需要根据参数提供多种初始化方法。除了可选命名参数和可选参数之外,Dart还提供了命名构造函数的方式,使得类的实例化过程语义更清晰。

此外,与C++类似,Dart支持初始化列表。在构造函数的函数体真正执行之前,还有机会给实例变量赋值,甚至重定向至另一个构造函数。

class Point {
num x, y, z;
Point(this.x, this.y) : z = 0; // 初始化变量z
Point.bottom(num x) : this(x, 0); // 重定向构造函数
void printInfo() => print('($x, $y, $z)');
} var p = Point.bottom(100);
p.printInfo(); // 输出(100,0,0)

复用

在面向对象的编程语言中,将其他类的变量与方法纳入本类中进行复用的方式一般有两种:继承父类和接口实现。

在Dart中,可以对同一个父类进行继承或接口实现:
  • 继承父类意味着,子类由父类派生,会自动获取父类的成员变量和方法实现,子类可以根据需要覆写构造函数及父类方法;
  • 接口实现则意味着,子类获取到的仅仅是接口的成员变量符号和方法符号,需要重新实现成员变量,以及方法的声明和初始化,否则编译器会报错。
class Point {
num x = 0, y = 0;
void printInfo() => print('($x, $y)');
} // Vector 继承自 Point
class Vector extends Point { num z = 0;
@override
void printInfo() => print('($x,$y,$z)'); // 覆写了printInfo实现
} // Coordinate 是对 Point 的接口实现
class Coordinate implements Point { num x = 0, y = 0; // 成员变量需要重新声明
void printInfo() => print('($x, $y)'); // 成员函数需要重新声明实现
} var xxx = Vector();
xxx
..x = 1
..y = 2
..z = 3; // 级联运算符,等同于 xxx.x = 1; xxx.y = 2; xxx.z = 3;
xxx.printInfo(); // 输出(1,2,3) var yyy = Coordinate();
yyy
..x = 1
..y = 2; // 级联运算符,等同于 yyy.x = 1; yyy.y = 2;
yyy.printInfo(); // 输出 (1,2)
print(yyy is Point); // true
print(yyy is Coordinate); // true
除了继承和接口实现之外,Dart还提供了另一种机制来实现类的复用,即“混入"(Mixin),混入鼓励代码重用,可以被视为具有实现方法的接口。不仅可以解决Dart缺少对多重继承的支持问题,还能够避免由于多重继承可能导致的歧义(菱形问题)。

要使用混入,只需要with关键字即可。

class Coordinate with Point {

}

  var yyy = Coordinate();
yyy
..x = 1
..y = 2; // 级联运算符,等同于 yyy.x = 1; yyy.y = 2;
yyy.printInfo(); // 输出 (1,2)
print(yyy is Point); // true
print(yyy is Coordinate); // true
可以看到,通过混入,一个类里可以以非继承的方式使用其他类中的变量与方法。

运算符

Dart和绝大多数编程语言的运算符一样,除外,Dart多了几个额外的运算符,用于简化处理变量实例缺失(即null)的情况。
  • ?. 运算符:假如Point类有printInfo()方法,p是Point的一个可能为null的实例。那么,p调用成员方法的安全代码,可以简化为p?.printInfo(),表示p为nul的时候跳过,避免抛出异常。
  • ??= 运算符:如果a为null,则给a赋值value,否则跳过。这种用默认值兜底的赋值语句在Dart中我们可以用a ??= value表示。
  • ?? 运算符:如果a不为null,返回a的值,否则返回b。在Java或者C++中,我们需要通过三元表达式(a != null)? a:b 来实现这种情况。而在Dart中,这类代码可以简化为 a ?? b。
在Dart中,一切都是对象,就连运算符也是对象成员函数的一部分。
对于系统的运算符,一般情况下只支持基本数据类型和标准库中提供的类型。而对于用户自定义的类。如果想要支持基本操作,比如比较大小、相加相减等,则需要用户自己来定义关于这个运算符的具体实现。

Dart提供了类似C++的运算符覆写机制,使得我们不仅可以覆写方法,还可以覆写或者自定义运算符。

class Vector {
num x, y;
Vector(this.x, this.y);
// 自定义相加运算符,实现向量相加
Vector operator + (Vector v) => Vector(x + v.x, y + v.y); // 覆写相等运算符,判断向量相等
bool operator == (dynamic v) => x == v.x && y == v.y;
} final x = Vector(3,3);
final y = Vector(2,2);
final z = Vector(1,1);
print(x==(y+z)); // 输出 true
operator 是 Dart 的关键字,与运算符一起使用,表示一个类成员运算符函数。在理解时,我们应该把 operator 和运算符作为整体,看作是一个成员函数名。

Dart函数、类和运算符-处理信息的更多相关文章

  1. 编写可维护的JavaScript—语句和表达式&变量、函数和运算符

    语句和表达式 所有的块语句都应当使用花括号.包括: if for while do…while… try…catch…finally //不好的写法 if (condition) doSomethin ...

  2. 使用工厂方法模式设计能够实现包含加法(+)、减法(-)、乘法(*)、除法(/)四种运算的计算机程序,要求输入两个数和运算符,得到运算结果。要求使用相关的工具绘制UML类图并严格按照类图的设计编写程序实

    2.使用工厂方法模式设计能够实现包含加法(+).减法(-).乘法(*).除法(/)四种运算的计算机程序,要求输入两个数和运算符,得到运算结果.要求使用相关的工具绘制UML类图并严格按照类图的设计编写程 ...

  3. 1、使用简单工厂模式设计能够实现包含加法(+)、减法(-)、乘法(*)、除法(/)四种运算的计算机程序,要求输入两个数和运算符,得到运算结果。要求使用相关的工具绘制UML类图并严格按照类图的设计编写程

    1.使用简单工厂模式设计能够实现包含加法(+).减法(-).乘法(*).除法(/)四种运算的计算机程序,要求输入两个数和运算符,得到运算结果.要求使用相关的工具绘制UML类图并严格按照类图的设计编写程 ...

  4. C++友元函数和运算符重载

    非成员友元函数.成员友元函数和友元类 1.友元的作用: (1)友元提供了不同类的成员函数之间.类的成员函数与一般函数之间进行了数据共享的机制: 2.友元的优点和缺点 优点:提高程序的运行效率: 缺点: ...

  5. Shell编程基础教程2--变量和运算符

    2.变量和运算符 2.1.变量的类型 本地变量:环境变量:变量替换(显示变量):位置变量:标准变量:特殊变量: 2.2.本地变量 本地变量在用户现在的shell生命周期的脚本中使用 在命令行, LOC ...

  6. Javascript学习2 - Javascript中的表达式和运算符

    原文:Javascript学习2 - Javascript中的表达式和运算符 Javascript中的运算符与C/C++中的运算符相似,但有几处不同的地方,相对于C/C++,也增加了几个不同的运算符, ...

  7. JavaScript深入浅出补充——(一)数据类型,表达式和运算符

    项目基本做完,在进行下一阶段学习之前先看视频学习回顾一下JavaScript 一.数据类型 JavaScript中有五种原始类型和一种对象类型 JavaScript弱类型语言中隐式转换 num-0 字 ...

  8. Java 第二章 变量、数据类型和运算符

    第二章      变量.数据类型和运算符 什么是变量: 变量代表一块内存区域,变量类型不一样,这一块内存的大小也不一样. #在编程语言里面,你可以通过定义变量,向内存里添加数据或者修改内存已有的数据. ...

  9. C#图解教程 第八章 表达式和运算符

    表达式和运算符 表达式字面量 整数字面量实数字面量字符字面量字符串字面量 求值顺序 优先级结合性 简单算术运算符求余运算符关系比较运算符和相等比较运算符递增运算符和递减运算符条件逻辑运算符逻辑运算符移 ...

随机推荐

  1. python3:面向对象(多态和继承、方法重载及模块)

    1.多态 同一个方法在不同的类中最终呈现出不同的效果,即为多态. class Triangle: def __init__(self,width,height): self.width = width ...

  2. 【原】UILabel 设置了 attributedText 后省略号不显示

    在开发中,对于一个 UILabel 我们都会设置 lineBreakMode 属性. 我在开发中就遇到个比较有意思的问题,所以就写了这篇博客,与大家共勉! 对于一个 UILabel ,我先设置了 se ...

  3. python 编码报错问题 'ascii' codec can't encode characters 解决方法

    python在安装时,默认的编码是ascii, 当程序中出现非ascii编码时,python的处理常常会报这样的错 'ascii' codec can't encode characters pyth ...

  4. java 正则 替换中文为空

    //中文替换为"" public String replaceChineseToNULL(String s){ String reg = "[\u4e00-\u9fa5] ...

  5. java 判断 string 转 integer 判断

    NumberUtils.isDigits("1") NumberUtils.isDigits("/") 根据返回 true false 再确定是否转换即可 需要 ...

  6. 2015-11-13 linux基础笔记

    1.安装linux 使用光盘,版本CENSOS6.6 2.命令过长请使用\  后enter键换行转义  直到不需要转义后回车运行 3.linux 大小写敏感 4.显示terminal 输出语言  ec ...

  7. 使用spark dataSet 和rdd 解决 某个用户在某个地点待了多长时间

    现有如下数据文件需要处理格式:CSV位置:hdfs://myhdfs/input.csv大小:100GB字段:用户ID,位置ID,开始时间,停留时长(分钟) 4行样例: UserA,LocationA ...

  8. PicGo+GitHub:你的最佳免费图床选择!

    # PicGo介绍 这是一款图片上传的工具,目前支持SM.MS图床,微博图床,七牛图床,腾讯云COS,阿里云OSS,Imgur,又拍云,GitHub等图床,未来将支持更多图床. 所以解决问题的思路就是 ...

  9. C#窗体--鼠标事件

    常见的鼠标事件: mouseclick,mousedown,mouseup,mousuenter,mouseleave.mousemove mouseDown按下鼠标事件: //鼠标按下后显示 pri ...

  10. 设计模式(C#)——04原型模式

    推荐阅读:  我的CSDN  我的博客园  QQ群:704621321       在软件开发过程中,我们习惯使用new来创建对象.但是当我们创建一个实例的过程很昂贵或者很复杂,并且需要创建多个这样的 ...