类和对象
- 使用
class
关键字声明一个类 - 可以使用
new
跟上构造函数 - 所有的对象都继承
Object
类 - 声明一个类的成员变量要有默认值,如果没有默认值需要写上
?
代表可选类型。 - Dart中默认生成
getter
和setter
方法 - 属性和方法都通过点语法访问
-
final
修饰的属性,必须定义初始值 - 如果没有赋值初始值,可以在构造函数中添加
void main() {
SJPerson person = SJPerson();
person.name = 'sj';
person.age = 18;
person.run();
}
class SJPerson {
String? name;
int? age;
// SJPerson(this.name);
void run() {
print('name:$name, age:$age');
}
}
作用域权限
- 同一份文件中可以随意访问
- 不同文件中使用
_
开头的成员变量和方法,不能被外界访问
// sj_person.dart
class SJPerson {
String? _name;
int? _age;
// SJPerson(this.name);
void _run() {
print('name:$_name, age:$_age');
}
void initValue(String name, int age) {
_name = name;
_age = age;
}
void printP() {
_run();
}
}
// main.dart
import 'sj_person.dart';
void main() {
SJPerson person = SJPerson();
person.initValue('sj', 18);
person.printP();
Animal a = Animal();
a._name = '123';
}
class Animal {
String? _name;
}
构造函数
类默认有一个构造函数,如果我们自定义了构造函数,默认的构造函数就没有作用了。
自定义构造函数给成员变量赋值,可以使用this.
语法糖直接赋值。
void main() {
SJTeacher t = SJTeacher('jx', 30);
}
class SJTeacher {
String? name;
int? age;
SJTeacher(this.name, this.age);
}
命名构造函数
void main() {
SJPerson person = SJPerson.withName(16);
}
class SJPerson {
String? _name;
int? _age;
SJPerson(this._name);
SJPerson.withName(this._age);
}
使用final
修饰的好处是,代表这个成员是常量,如果一个类的成员都是final
修饰,构造函数前可以加const
修饰,这时我们再创建出来的对象就是常量对象,可以节约内存。
class SJTeacher {
final String name;
final int age;
const SJTeacher(this.name, this.age);
}
单利
构造方法正常是不用写返回对象的,如果想返回对象,需要再方法前写上factory
,工厂构造方法。
class FactoryClass {
static FactoryClass? instance;
factory FactoryClass() {
if (instance == null) {
instance = FactoryClass._init();
}
return instance!;
}
/// 私有的命名构造函数
FactoryClass._init();
}
简化如下:
void main() {
FactoryClass c1 = FactoryClass();
FactoryClass c2 = FactoryClass();
print(c1 == c2);
}
class FactoryClass {
static FactoryClass? _instance;
factory FactoryClass() => _instance ??= FactoryClass._init();
/// 私有的命名构造函数
FactoryClass._init();
}
初始化列表
构造函数后面加:
,后面的内容就是初始化列表。
目的:
- 给
final
变量赋值,它会在初始化之前给列表变量赋值 - 校验传递的值,这是最常用也是最主要的功能
class Person {
String name;
int age;
final height;
Person(this.name, a, h)
: height = h,
age = a,
assert(h >= 0),
assert(a > 0) {
print("hahahhaha");
}
Person.init2(this.name, a, h)
: height = h,
age = a;
}
类方法
- 静态属性、静态方法用类名直接访问。
- 静态方法不能访问非静态成员。静态方法是类对象调用的,非静态成员是实例对象初始化后才出来的,这时候还没有实例对象,所以不能访问。
- 实例方法可以直接访问静态属性。实例对象创建时候,静态属性一定在,所以可以访问。
- 常量属性需要用
static
修饰
void staticDemo() {
StaticClass.count;
StaticClass.sum(2);
StaticClass s = StaticClass();
print(s.sum2(3));
}
class StaticClass {
// 静态属性
static int count = 1;
int count2 = 2;
static const String name = 'sj';
/// 静态方法
static sum(int a) {
return a + count;
}
int sum2(int a) {
return a + count + count2;
}
}
对象操作符
用var
声明变量是动态类型,值可能为null
,这时直接执行方法可能会报错,我们把变量后面加个?
执行就可以了。
void dynamicDemo() {
var s;
s = StaticClass();
s.sum2(2);
s = null;
s?.sum2(2);
}
强制类型转换使用as
,转换完后面就能用这个转换的类型了。
使用if
判断类型,if
里面也可以直接使用此类型。
void mapDemo() {
var s = Object();
s = StaticClass();
if (s is StaticClass) {
print(s.sum2(2));
}
// print((s as StaticClass).sum2(2));
// print(s.sum2(2));
}
使用..
链式编程
void chainedDemo() {
StaticClass s = StaticClass();
s..count2 = 10..sum2(2);
}
继承
/**
* Dart中的继承
* 使用extends继承一个类
* 子类会继承除了构造方法意外的属性和方法
* 默认构造方法会自动继承
* 如果是有参数或者有名字的构造方法,子类需要显性使用super,实现一个即可
* Dart是单继承
* 子类重写父类方法使用@override,不写可以,但是不建议
* super使用可以和初始化列表一起,super要放到最后
* */
void extendsDemo() {
S2 s = S2('sj');
print(s);
}
class S1 {
S1.initValue();
S1(this.age);
void run() {
print('run');
}
int age = 10;
}
class S2 extends S1 {
final String name;
// S2.initValue() : super.initValue();
S2(String n)
: name = n,
super.initValue();
@override
void run() {
// TODO: implement run
super.run();
}
// Object的toString方法类似OC的description方法
@override
String toString() {
// TODO: implement toString
return 'S2 extends S1';
}
}
抽象类
/**
* 抽象类
* 不能被实例化的类,使用abstract修饰
* 子类可以被实例化,子类必须实现父类的抽象方法
* 多态对象不用判断类型,因为子类必须实现父类的抽象方法
* 子类可以实现多个抽象类,使用implements,实现需要实现所有方法和属性
* */
abstractDemo() {
SubClass a = SubClass();
a.sum(10, 20);
}
abstract class AbstractClass {
/// 这就是抽象方法
int sum(int a, int b);
}
abstract class AbstractClass1 {
/// 这就是抽象方法
int minus(int a, int b);
}
class NormalClass {
var name;
void run() {}
}
class SubClass implements AbstractClass, AbstractClass1, NormalClass {
@override
int sum(int a, int b) {
return a + b;
}
@override
int minus(int a, int b) {
return a - b;
}
@override
var name;
@override
void run() {}
}
Mixins 混入
/**
* 混入
* 说白了就是多继承
* 混入如果有一样的方法,会执行最后一个混入的类的方法
* 作为混入的类,是不能实现构造方法的,且不能继承非Object类
* */
mixinsDemo() {
DClass d = DClass();
d.a();
// d.b();
// d.c();
}
class AClass {
AClass();
a() => print('a ...');
}
class BClass {
a() => print('b ...');
}
class CClass {
a() => print('c ...');
}
// class DClass extends AClass with BClass, CClass {}
// 如果DClass没有成员和方法,可简写成下面
class DClass = AClass with BClass, CClass;
重载操作符
使用operayor
operatorDemo() {
OperatorClass o1 = OperatorClass(18);
OperatorClass o2 = OperatorClass(15);
print(o1 > o2);
}
class OperatorClass {
int age;
OperatorClass(this.age);
bool operator >(OperatorClass o) => this.age > o.age;
}
网友评论