Dart 和Java一样,也是一个面向对象的编程语言。每一个对象都是一个类的实例,并且这些类都是从Object派生出来的,只有Null除外。这句话换个角度理解就是除了Null之外,所有的class都有父类。要么有直接通过imple或者是extend继承的父类;要么就是继承自默认的Object类。
声明一个类
其实前面的一些例子里有声明过一些类。 通过class关键字去声明一个类。
arduino
class Person { //隐式继承自Object父类。
String name; //变量属性
int age;
String address;
Person(this.name, this.age, this.address);//构造方法
void fight() { //方法
print("I am fighting");
}
}
类创建完了之后,我们通过new关键字去实例化一个类,也就是创建一个类对象。当然,new关键字也是可以省略的。
dart
var tony = Person("Tony", 20, "New York");//省略了new
print('${tony.name} is ${tony.age} years old and lives in ${tony.address}');
var wang = Person("Wang", 20, "New York");
print('${wang.name} is ${wang.age} years old and lives in ${wang.address}');
构造函数
构造函数是类中的一个特殊方法,所有类中的都会有构造函数,如果没有自定义构造函数,则该类就会有一个默认的构造函数,该构造函数没有任何参数。
这里先介绍几个常用的构造函数
- 默认构造函数
- 普通构造函数
- 静态构造函数
默认构造函数
如果定义了一个类,没有自定义构造函数,则该类就会使用默认构造函数。在实例化的时候就可以通过这个默认构造函数去创建改类的实例。
csharp
class Person { //隐式继承自Object父类。
void fight() { //方法
print("I am fighting");
}
}
void main() {
var tony = Person(); // 创建一个person实例,并赋值给tony这个变量
tony.fight() // 调用该实例的方法
}
如果自定义了一个构造函数,则该默认构造函数就不会存在了。
自定义构造函数
自定义构造函数最简单的方式就是命名一个和类同名的方法,不需要定义返回值,然后可以将一些需要在初始化的时候就赋值的参数放在构造方法中,由于Dart中具有丰富的可选参数功能,所以就不用像Java那样去定义多个构造函数来达到多态这种情况,但可以通过可选参数的方式去达到Java中那种多态的效果。
dart
class Person { //隐式继承自Object父类。
String name; //变量属性
int age;
String? address;
Person(this.name, this.age, [this.address]);//构造方法
void fight() { //方法
print("I am fighting");
}
}
void main() {
var tony = Person("Tony", 20, "New York");//创建一个person实例,并赋值给tony这个变量
print('${tony.name} is ${tony.age} years old and lives in ${tony.address}'); //使用实例的属性
var wang = Person("Wang", 20);//创建一个person实例,并赋值给tony这个变量
print('${tony.name} is ${tony.age} years old.);
}
由于address这个参数是可选的,所以我可以在实例化的时候不给他赋值。
常量构造函数
如果你想要一个类在实例化之后,里面的成员属性的值是不可变的。那么可以用const来定义这个构造函数。同样,如果你的构造函数声明添加了const关键字,则它的属性就必须添加final声明。
如:
arduino
class ImmutablePoint {
final int x;
final int y;
const ImmutablePoint(this.x, this.y); //常量构造函数
}
实例变量
这是一个关于如何声明实例变量的例子,这个例子里包含了几种我们常见情况。
arduino
class Point {
double? x; // 声明一个变量x,初始化值为null
double z = 100; // 声明一个变量z,初始化值为0
final double y; // 声明一个变量y,未被初始化
late double sum = (x ?? 0) + y + z;//延迟初始化
Point(this.y); // 创建这个类的时候必须初始化y,因为它是final类型且不为null
}
void main() {
var point = Point(10.0);
point.x = 20.0;
print(point.sum);
}
- 第一个是声明一个可空类型的变量,默认初始值为null。
- 第二个是声明一个不可空的变量。初始值是0。
- 定一个不可变的变量,由于在定义的时候没有初始化,所以必须在构造函数的时候初始化。
- 声明一个延迟初始化变量。
获取实例的类型
有时候在允许期间,可能不知道该实例的类型是什么,则可以通过runtimeType参数获取。如:
dart
print('The type of a is ${a.runtimeType}');
这样就可以打印出a的类型的名字。
隐式接口
这点Dart和Java有点不太一样,在Dart中,如果你用class定义了一类,这个了
dart
//person类,隐式接口类包含greet方法
class Person {
// 这是一个只能在当前文件中可见的属性。之前了解过的。可以被当作interface的参数,被继承复写
final String _name;
Person(this._name); //这是构造函数,不能被继承
// 这是一个方法,可以被当作interface中的一个方法,可以被继承复写。
String greet(String who) => 'Hello, $who. I am $_name.';
}
// An implementation of the Person interface.
class Impostor implements Person {
String get _name => ''; //复写父类的_name参数
// 复写父类的greet方法
String greet(String who) => 'Hi $who. Do you know who I am?';
}
String greetBob(Person person) => person.greet('Bob');
void main() {
print(greetBob(Person('Kathy')));
print(greetBob(Impostor()));
}
上面这个例子通过注释的方式简要的说明了一个class如何被当作一个隐式接口来用的。
静态变量和方法
Dart中的静态变量主要是通过static来修饰
静态变量
arduino
class Queue {
static const initialCapacity = 16; // 静态变量
// ···
}
静态变量的用法和Java还是比较相似的。都是需要加static变量来修饰。
静态方法
静态方法和JAVA差不多,都是可以直接访问的,不需要创建实例。
ini
import 'dart:math';
class Point {
double x, y;
Point(this.x, this.y);
static double distanceBetween(Point a, Point b) {
var dx = a.x - b.x;
var dy = a.y - b.y;
return sqrt(dx * dx + dy * dy);
}
}
void main() {
var a = Point(2, 2);
var b = Point(4, 4);
var distance = Point.distanceBetween(a, b);
assert(2.8 < distance && distance < 2.9);
print(distance);
}
到此,差不多类的一些基本是介绍差不多。如果还想了解更多就去了解一些进阶的内容了。