不支持public、private等访问修饰符,一般约定_开头的变量为私有的,但是只是约定,实际还是可以访问到
// 使用class关键字定义类 class Rectangle { // 两个成员变量,变量名加_表示是私有的,只是一种约定,实质仍然能访问到 double _height; double _width; // 静态成员变量无需实例化即可通过类型访问 static String name = "长方形"; Rectangle(double width, double height) { this._width = width; this._height = height; } // 非命名构造方法若只是为成员变量赋值也可以这样写,与上边写法等价 // Rectangle(this._width, this._height); // 命名构造方法 Rectangle.fromMap(Map<String, double> map) { this._width = map['width']; this._height = map['height']; } static String getName() { // return this._height.toString(); 错误, 静态成员方法不能使用this,不能使用非静态成员变量 return name; } double getArea() { return _height * _width; } // double getArea 已存在,不能这样写,不支持重载 // double getArea(double width, double height) { // // } // get set方法 double get width { print("调用 get width"); return _width; } set width(double value) { print("调用set width"); _width = value; } double get height => _height; set height(double value) { _height = value; } } void main() { print(Rectangle.name); print(Rectangle.getName()); Rectangle rectangle = Rectangle.fromMap({'width': 10, 'height': 20}); print(rectangle.getArea()); rectangle.width = 1; print(rectangle.width); } 继承要点:
使用extends关键字
只支持单继承
子类可以获得父类的普通成员方法和普通成员变量,无法得到静态成员,构造方法也继承不到
可以重写父类的方法,可以使用super访问父类
如果父类没有无参构造的话,子类必须显示调用父类的构造,否则报错
// 使用extends继承 class Square extends Rectangle { // 默认会访问父类的无参构造,如果父类没有无参构造需要这样显式指定调用哪个构造 Square(double width):super(width, width); // 重写父类的方法 @override double getArea() { // 使用super访问父类的成员变量 print('重写父类方法: ${super._width}'); // 使用super访问父类的成员方法 return super.getArea(); } } void main() { // Square.getName(); 错误, 无法继承静态成员 // Square.name; 错误,无法继承静态成员 Square square = Square(10); print(square.getArea()); print(square._width); } 抽象类要点:
在class前加abstract关键字定义抽象类
抽象类不能被实例化,只能被继承(后面会讲到,也可以被当成接口实现)
抽象类可以有抽象方法(不含方法体的方法),也可以有普通方法和成员变量
继承抽象类的类,要么重写其所有抽象方法,要么该类也要被被定义为抽象类,要么增加一个noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);方法
// 定义一个抽象类 abstract class Shape { // 抽象方法,没有方法体 double getArea(); double getPerimeter(); } class Rectangle extends Shape { double _height; double _width; Rectangle(double width, double height) { this._width = width; this._height = height; } Rectangle.fromMap(Map<String, double> map) { this._width = map['width']; this._height = map['height']; } // 必须重写抽象类的抽象方法,否则需要也要声明为抽象类 @override double getArea() { return _height * _width; } // 必须重写抽象类的抽象方法 @override double getPerimeter() { return _height + _width; } } void main() { // Shape shape = Shape(); 错误,抽象类不能被实例化 Shape shape = Rectangle(10, 2); // 这样是可以的 print(shape.getArea()); print(shape.getPerimeter()); } 接口关于接口,dart的设计比较奇怪。
官方文档对接口描述一下
每一个类都显式的声明了一个包含其成员变量和成员方法及他实现的接口的接口。如果你想创建一个支持B类API的类,实现B类就好了。
也即定义一个类就相当于定义了一个接口,可以直接去实现他,也可以实现多个接口。extends只能继承一个类,implements可以实现多个类(抱歉恨不厚道的说了实现一个类,这里应为接口)。
在上一个例子中直接写成下边这样也是可以的
class Rectangle implements Shape 泛型dart提供了对泛型的支持,泛型可以增加程序的通用性,并可提供一些静态检查,减少了一些强制类型转换的工作。
// 定义一个泛型类 class Cache<T> { Map<String, T> _cache = {}; T getByKey(String key) { return _cache[key]; } // 泛型方法 void setByKey(String key, T value) { _cache[key] = value; } } // 做类型约束,必须是num的子类 class NumCache<T extends num> { Map<String, T> _cache = {}; T getByKey(String key) { return _cache[key]; } void setByKey(String key, T value) { _cache[key] = value; } } void main() { Cache<String> cache = Cache(); cache.setByKey("a", "1"); // cache.setByKey("b", 2); 错误,类型不匹配 print(cache.getByKey("a") is String); // 类型被保持, 输出true // NumCache<String> numCache = NumCache(); 错误String不是num的子类 NumCache<int> numCache = NumCache(); numCache.setByKey('a', 1); } 异常要点:
无需显式指定抛出哪些异常,这与java不同,java需要使用throws 异常类
不是必须对异常处理,java如果有throws那么必须捕获
有Error、Exception及其子类作为异常类,也可自定义
抛出异常时可以抛出异常类,也可以抛出非null的任何对象