0
点赞
收藏
分享

微信扫一扫

Dart 类与方法详解


人生富贵驹过隙,惟有荣名寿金石 —— 顾炎武


Dart 类与方法详解

    Dart 是一种基于类和 mixin 继承机制的面向对象的语言。 每个对象都是一个类的实例,所有的类都继承于 Object【而且Dart 中的继承和Java的一样都是单继承的语言,不像C++可以多继承】

对象

    对象由函数数据【即方法和实例变量】组成。
    方法的调用要通过对象来完成: 调用的方法可以访问其对象的其他函数和属性,使用 . 来引用实例对象的变量和方法

创建对象

    创建对象的前提是得有类,那我们就得先定义一个类,定义类的关键字和 Java 语言一样都是 class 关键字

// 定义一个 Person 类
class Person {
String username = ''; // 定义一个用户名
int age = 0; // 定义一个年龄
}

void main() {
// 创建一个Person 对象
Person p = new Person(); // 这个new 关键字是可以省略的,不过就是java写惯了还是这种舒服
p.age = 20; // 当然了返回类型Person 也可以用 var 来代替,这种都是支持的
print(p.age); // 并调用其对象的默认age属性值
}

    输出结果
Dart 类与方法详解_java

构造函数

    上面我们在创建对象的时候没有给与进行赋值,所以Dart也提供了在创建对象的时候进行赋值的方法,通过创建一个与其类同名的函数来声明构造函数

class Person {
String username = ''; // 定义一个用户名
int age = 1; // 定义一个年龄
// 定义一个构造函数
Person(String username,int age){
// 使用 this 关键字引用当前实例
this.username = username;
this.age = age;
}
}

void main() {
Person p = new Person('zhangsan',123); // new 关键字是可选的
print(p.age);
}

    输出结果
Dart 类与方法详解_前端_02
    构造函数语法糖,通常模式下,会将构造函数传入的参数的值赋值给对应的实例变量, Dart 自身的语法糖精简了这些代码

class Person {
String username = ''; // 定义一个用户名
int age = 1; // 定义一个年龄
Person(this.username,this.age);
}

void main() {
Person p = new Person('zhangsan',23);
print(p.age);
}

默认构造函数

    在没有声明构造函数的情况下, Dart 会提供一个默认的构造函数。 默认构造函数没有参数并会调用父类的无参构造函数【这一点和 Java 一样】,子类不会继承父类的构造函数。 子类不声明构造函数,那么它就只有默认构造函数,而且在执行主类构造函数之前一定会执行父类的构造函数,毕竟先进行父类初始化,不然哪来的子类呢

常量构造函数

    如果该类生成的对象是固定不变的, 那么就可以把这些对象定义为编译时常量。 需要定义一个 const 构造函数, 并且声明所有实例变量为 final,使用常量构造函数,在构造函数名之前加 const关键字

class ImmutablePoint {
static final ImmutablePoint origin = const ImmutablePoint(0, 0);
final num x, y;
const ImmutablePoint(this.x, this.y);
}

void main() {
ImmutablePoint p = const ImmutablePoint(2, 2);
}

    注意:构造两个相同的编译时常量会产生一个唯一的, 标准的实例

命名构造函数

    使用命名构造函数可为一个类实现多个构造函数, 也可以使用命名构造函数来更清晰的表明函数意图【这种方式其实在 java 中就是多态的方式,只不过在 Dart 中是不同的名称罢了】

class Person {
String username = ''; // 定义一个用户名
int age = 1; // 定义一个年龄
Person(this.username,this.age);
// 命名构造函数
Person.origin() {
username = 'haha';
age = 1;
}

}
void main() {
Person p = new Person('zhangsan',23);
Person p_1 = new Person.origin();
print(p.age);
print(p_1.age);
}

    输出结果
Dart 类与方法详解_java_03

重定向构造函数

    有时构造函数的唯一目的是重定向到同一个类中的另一个构造函数。 重定向构造函数的函数体为空,构造函数的调用在冒号:之后

class Person {
String username = ''; // 定义一个用户名
int age = 1; // 定义一个年龄
Person(this.username,this.age);
// 命名构造函数
Person.origin() {
username = 'haha';
age = 1;
}
// 从定向构造函数指向主构造函数
Person.alongXAxis(String username) : this(username, 0);

}

void main() {
Person p = new Person('zhangsan',23);
Person p_1 = new Person.origin();
Person p_2 = new Person.alongXAxis('lallala');
print(p.age);
print(p_1.age);
print(p_2.username);
}

    输出结果
Dart 类与方法详解_抽象类_04

工厂构造函数

    当执行构造函数并不总是创建这个类的一个新实例时,则使用 factory关键字。 例如,一个工厂构造函数可能会返回一个 cache 中的实例,通过这种方式就提高了效率以及提高了内存的使用率,当内存中有实例的情况下就不需要进行创建新实例了

void main() {
var logger = Logger('UI');
// 调用实例中的方法
logger.log('Button clicked');
}

class Logger {
final String name;
bool mute = false;
// 从命名的 _ 可以知,_cache 是私有属性。
static final Map<String, Logger> _cache = <String, Logger>{};

factory Logger(String name) {
// 判断缓存中是否有这个对象值,如果有的话直接返回,没有的话进行创建
if (_cache.containsKey(name)) {
return _cache[name]!;
} else {
final logger = Logger._internal(name);
_cache[name] = logger;
return logger;
}
}
// 生命的构造方法
Logger._internal(this.name);
void log(String msg) {
if (!mute) print(msg);
}
}

方法

    方法是为对象提供行为的函数,也就是进行了对象的创建之后就可以调用其对应的方法

Getter与Setter

    Getter 和 Setter 是用于对象属性读和写的特殊方法。每个实例变量都有一个隐式 Getter ,通常情况下还会有一个 Setter 。 【java语言中需要自己将其声明出来,不然的话不会有这个方法的】
    使用 getset关键字实现 Getter 和 Setter ,能够为实例创建额外的属性【长方形案例】

class Rectangle {
num left, top, width, height;
// 构造函数
Rectangle(this.left, this.top, this.width, this.height);
// 定义两个计算属性: right 和 bottom。
num get right => left + width;
set right(num value) => left = value - width;
num get bottom => top + height;
set bottom(num value) => top = value - height;
}

void main() {
var rect = Rectangle(3, 4, 20, 15);
print(rect.left);
rect.right = 12;
print(rect.left);
}

    输出结果
Dart 类与方法详解_构造函数_05
    原始的对象实例的默认的 Getter 和 Setter 也许是直接返回成员变量,但是随着需求变化 Getter 和 Setter 可能需要进行计算处理

抽象类

    使用 abstract修饰符来定义抽象类,抽象类不能实例化。 抽象类通常用来定义接口,以及部分实现。 如果希望抽象类能够被实例化,那么可以通过定义一个工厂构造函数来实现,抽象类通常具有抽象方法抽象方法是没有函数体的

// 定义一个抽象的动物类,这个类被定义为抽象类,所以不能被实例化。
abstract class Animal {
// 定义构造行数,字段,方法...
void fly(); // 抽象方法。
}
// 定义一个鸟类进行动物类的继承之后实现其方法
class Bird extends Animal{
void fly(){
print('i can fly');
}
}
void main() {
Bird b = new Bird();
b.fly();
}

    输出结果
Dart 类与方法详解_java_06

总结

    Dart 提供的类和对象的信息其实和其他面向对象的语言挺像的,比如以下几点:

  1. 在进行类继承的时候先执行父类的无参构造函数,之后在执行子类的无参构造函数
  2. 还有就是重定向构造函数和Java中的多态实现特别像
  3. 常量的构造函数其实和Java中的单例模式差不多
  4. 工厂构造函数是说白了就是将创建好的对象放入了缓存中罢了,并提高了效率
  5. 抽象类和抽象方法其实都和java语言提供的相似
举报

相关推荐

0 条评论