类
Dart所有的东西都是对象,所有的对象都继承自object类。
Dart是一门使用类和单继承的面向对象语言,所有的对象都是类的实例,并且所有的类都是object的子类
一个类通常由属性和方法组成。
Dart
中类的多态:
允许将子类类型的指针赋值给父类类型的指针,同一个函数调用会有不同的执行效果.
子类的实例赋值给父类的引用。
多态就是父类定义一个方法不去实现,让继承他的子类去实现,每个子类有不同的表现。
构造函数
跟类名一样的函数是构造函数
class Person {
String name = 'rh';
int age = 0;
Person(String name, int age) {
this.name = name;
this.age = age;
}
void getInfo() {
print('${this.name},${this.age}');
}
}
void main() {
var p = new Person('ronhai', 23);
p.getInfo();
}
class Person {
String name;
int age;
Person(this.name, this.age);
void getInfo() {
print('${this.name},${this.age}');
}
}
void main() {
var p1 = new Person('ronhai', 23);
p1.getInfo();
var p2 = new Person('隆海', 11);
p2.getInfo();
}
命名构造函数
命名构造函数可以建立多个
class Person {
String name = 'rh';
int age = 0;
Person(this.name, this.age);
Person.now() {
print('now命令构造函数');
}
Person.next() {
print('next命令构造函数');
}
void getInfo() {
print('${this.name},${this.age}');
}
}
void main() {
var p1 = new Person('ronhai', 23);
p1.getInfo();
var p2 = new Person('隆海', 11);
p2.getInfo();
var p3 = new Person.now();
var p4 = new Person.next();
}
私有属性和方法
Dart和其他面向对象语言不一样,Data中没有 public private protected这些访问修饰符合
但是我们可以使用_把一个属性或者方法定义成私有的
需要模块化,新建module.dart
class Person {
final _money = 10000;
Person() {}
void getMoney() {
print('银行存款${_money}');
}
}
func.dart
引用
import 'module.dart';
void main() {
var p1 = new Person();
p1.getMoney();
print(p1._money); # 报错不能访问,如果在一个文件里面是可以访问的
}
getter和setter
class Area {
num height = 0;
num width = 0;
Area(this.height, this.width);
get area {
return this.height * this.width;
}
}
void main() {
var r = new Area(100, 200);
print('面积:${r.area}');
}
class Area {
num height = 0;
num width = 0;
Area(this.height, this.width);
get area {
return this.height * this.width;
}
set areaHeight(value) {
this.height = value;
}
}
void main() {
var r = new Area(100, 200);
print('面积:${r.area}');
r.areaHeight = 6;
print(r.area);
}
静态属性和静态方法
Dart中的静态成员:
- 使用static 关键字来实现类级别的变量和函数
- 静态方法不能访问非静态成员,非静态方法可以访问静态成员
class Person {
static String name = '隆海';
int age = 20;
static void show() {
print(name);
}
void printInfo() {
print(name); //访问静态属性
print(this.age); //访问非静态属性
show(); //调用静态方法,直接调用不用this
}
}
void main() {
var p = new Person();
p.printInfo();
Person.show();
}
对象操作符
- ? 条件运算符
- as 类型转换
- is 类型判断
- .. 级联操作(连缀)
class Person {
static String name = '隆海';
int age = 20;
static void show() {
print(name);
}
void printInfo() {
print(name); //访问静态属性
print(this.age); //访问非静态属性
show(); //调用静态方法,直接调用不用this
}
}
void main() {
var p;
p?.printInfo();
}
class Person {
String name = '隆海';
int age = 20;
Person(String name, int age) {
this.name = name; // 初始化静态属性
this.age = age; // 初始化非静态属性
}
void show() {
print(this.name);
}
void printInfo() {
print(name); //访问静态属性
print(this.age); //访问非静态属性
show(); //调用静态方法,直接调用不用this
}
}
void main() {
Person p = Person('rh', 20);
p
..name = 'ronhai'
..age = 10
..printInfo();
/*
以上跟
p.name= 'ronhai';
p.age=10;
p.printInfo();
效果一样
*/
}
类的继成
Dart申的类的继承: 1、子类使用extends关键词来继承父类 2、子类会继承父类里面可见的属性和方法 但是不会继承构造函数 3、子类能复写父类的方法 getter和setter
抽像类
Dart中抽象类:Dart抽象类主要用于定义标准,子类可以继承抽象类,也可以实现抽象类接口.
- 抽象类通过abstract关键字来定义
- Dart中的抽象方法不能用abstract声明,Dart中没有方法体的方法我们称为抽象方法.
- 如果子类继承抽象类必须得实现里面的抽象方法
- 如果把抽象类当做接口实现的话必须得实现抽象类里面定义的所有属性和方法-1
- 抽象类不能被实例化,只有继承它的子类可以
extends抽象类和implements的区别:
- 如果要复用抽象类里面的方法,并且要用抽象方法约束自类的话我们就用extends继承抽象类
- 如果只是把抽象类当做标准的话我们就用implements实现抽象类
abstract class Animal {
eat();
}
class Cat extends Animal {
@override
eat() {
print('小狗类');
}
}
void main() {
var c = new Cat();
c.eat();
}
接口
和Java一样,dart也有接口,但是和Java还是有区别的。
首先,dart的接口没有interface关键字定义接口,而是普通类或抽象类都可以作为接口被实现。
同样使用implements关键字进行实现。
但是dart的接口有点奇怪,如果实现的类是普通类,会将普通类和抽象中的属性的方法全部需要覆写一遍。
而因为抽象类可以定义抽象方法,普通类不可以,所以一般如果要实现像Java接口那样的方式,
建议使用抽象类定义接口。
一个类实现多个接口
mixins
*“在面向对象编程语言中,****Mixin***是一个包含可供其他类使用的方法的类,而不必是其他类的父类。”
mixins
的中文意思是混入,就是在类中混入其他功能。
在Dart中可以使用mixins
实现类似多继承的功能
因为mixins
使用的条件,随着Dart版本一直在变,这里讲的是Dart2.x中使用mixins的条件:
1、作为mixins的类只能继承自object,不能继承其他类
2、作为mixins的类不能有构造函数
3、一个类可以mixins多个mixins类
4、mixins绝不是继承,也不是接口,而是一种全新的特性
mixin A {
void aMethod() {
print('A method');
}
}
mixin B on A {
void bMethod() {
print('B method');
}
}
class Base {}
class C extends Base with A, B {
void cMethod() {
print('C method');
}
}
void main() {
C c = C();
c.aMethod(); // 输出: A method
c.bMethod(); // 输出: B method
c.cMethod(); // 输出: C method
}
在这个示例中:
A
和B
是mixins
,分别使用mixin
关键字定义。B
使用on
关键字指定它只能被混入到继承了A
的类中。C
类继承了Base
并混入了A
和B
,因此它可以访问A
和B
中的方法。
泛型
通俗理解:泛型就是解决类接口方法的复用性、以及对不特定数据类型的支持(类型校验)
泛型方法
T getData<T>(T value) {
return value;
}
//方法名前的T是返回类型,getData的T是传入类型
void main() {
var a = getData<String>('ronhai');
print(a);
var b = getData<int>(123);
print(b);
}
泛型类
普通一个类一个类型
class MyList {
List list = <int>[];
void add(int value) {
list.add(value);
}
List getList() {
return list;
}
}
void main() {
MyList l = MyList();
l.add(1);
l.add(12);
print(l.getList());
}
泛型类支持int类型和String类型的数据
class MyList<T> {
List list = <T>[];
void add(T value) {
list.add(value);
}
List getList() {
return list;
}
}
void main() {
MyList l1 = MyList<int>();
l1.add(1);
l1.add(12);
print(l1.getList());
MyList l2 = MyList<String>();
l2.add('rh');
l2.add('ronhai');
l2.add('隆海');
print(l2.getList());
}
泛型接口
和泛型的类一样,官方示例
abstract class ObjectCache {
Object getByKey(String key);
void setByKey(String key, Object value);
}
abstract class StringCache {
String getByKey(String key);
void setByKey(String key, String value);
}
abstract class Cache<T> {
T getByKey(String key);
void setByKey(String key, T value);
}
var names = <String>['Seth', 'Kathy', 'Lars'];
var uniqueNames = <String>{'Seth', 'Kathy', 'Lars'};
var pages = <String, String>{
'index.html': 'Homepage',
'robots.txt': 'Hints for web robots',
'humans.txt': 'We are people, not machines'
};
实现数据缓存的功能:有文件缓存、和内存缓存。内存缓存和文件缓有按照接口约束实现。
1、定义一个泛型接口约束实现它的子类必须有getByKey(key)和 setByKey(key,value)
2、要求setByKey的时候的value的类型和实例化子类的时候指定的类型一致
abstract class Cache<T> {
getByKey(String key);
void setByKey(String key, T value);
}
class SimpleCache<T> implements Cache<T> {
final Map<String, T> _cache = {};
@override
void setByKey(String key, T value) {
_cache[key] = value;
}
T? getByKey(String key) {
return _cache[key];
}
}
class FileCache<T> extends Cache<T> {
//文件缓存
@override
getByKey(String key) {
return null;
}
@override
void setByKey(String key, T value) {
print('我是文件缓存${key}');
}
}
class MemoryCache<T> extends Cache<T> {
//内存缓存
@override
getByKey(String key) {
return null;
}
@override
void setByKey(String key, T value) {
print('我是内存缓存${key}');
}
}
void main() {
var cache = SimpleCache<int>();
cache.setByKey('example', 42);
print(cache.getByKey('example')); // 输出: 42
MemoryCache m1 = new MemoryCache<String>();
m1.setByKey('index', '首页数据');
MemoryCache m2 = new MemoryCache<Map>();
m2.setByKey('index', {"name": "隆海", "age": 23});
}