dart学习(十)

class类

概述:类是对一类具有相同特征事物的描述,是实例的构造模板,是一个抽象概念 。例如,造汽车,首先我们得有制造图纸,图纸上绘汽车的底盘,轮胎,发动机等等,而我们根据图纸制造的出来的车就是这个图纸的一个实例(即类的实例化)。根据图纸我们我可制造很多相同的汽车出来,为了区分它们,我们会给每辆汽车一个编号,对应到代码层面,也就是一个类可以构造出多个数据结构相同的实例对象,而我们通过不同的引用来找到它们,实例化的时候系统会给每个实例在内存分配一个地址值来区分们,引用指向它们的地址值。

dart是一门面向对象语言,并且基于mixin-based多继承,每个对象都是一个类的实例。

1、类的声明:  class  类名 {}

以下划线或者大写字母开头,可以包含数字$(当然如果你小写字母开头并不会报错,但是约定俗成的都是以大写字母或下划线开头)

class Person {}

class _Person {}

注意:如果以下划线开头,表示这个类是私有的,只能在当前文件使用。

2、类的组成:方法,属性,构造器 

//一个简单类的声明
class Test {
  String name;
  Test(this.name);
  say() {}
}

①类的方法,分为静态方法和实例方法,静态方法用static关键字修饰,是属于类本身的

静态方法调用:类名.方法名()

实例方法调用:实例.方法名()

void main() {
  //类的方法调用
  Person.say();
  //实例方法调用
  Person p = new Person();
  p.eat();
}

class Person {
  static say() {
    print("静态方法");
  }

  eat() {
    print("实例方法");
  }
}

②类的属性,分为静态属性和实例属性

静态属性使用static  const 声明,并且在声明类的时候必须给其赋值

void main() {
  print(Person.age);
}

class Person {
  static const age = 23;
}

实例属性分为常量属性和变量属性,常量属性使用final关键字修饰,必须在实例化或者类声明的时候赋值,常量属性赋值后不能被修改。变量属性可以在实例化对象后通过对象来赋值

void main() {
  Person p = new Person("sixleg");
  p.age = 23;
  print(p.nation); //China
  print(p.name); //sixleg
  print(p.age); //23
}

class Person {
  final String nation = "China"; //常量属性,类声明时赋值
  final String name; //常量属性,实例化时赋值
  int age; //变量属性
  Person(this.name);
}

建议使用"?."代替"."来给实例属性赋值,这样可以避免当引用的值为null时程序报错

var p;
p.age = 23; //报错
p?.age = 23; //不会报错,如果p不为null,则赋值

③类的构造器,又叫构造方法

在dart中构造器不能被子类继承,构造器通过ClassName或者ClassName.identifier来命名,如果不显示声明构造器,dart会给每个类隐式添加一个无参名字跟类名相同的构造器,如果显示声明了构造器,则这个构造器不会存在,一个类可以有多个构造器。

class Person {
  String name;
  int age;
  Person() {} //无参构造器
  Person.fillName(String name) { //位置参数
    this.name = name;  //this关键字指向当前的实例对象
  }
  Person.fiiAge({int age}) { //命名参数
    this.age = age;
  }
}
//构造器可以简写,下面这种写法跟上面效果一样
//class Person {
//  String name;
//  int age;
//  Person();
//  Person.fillName(this.name);
//  Person.fiiAge({int this.age});
//}

构造器的调用,类实例化对象时调用对用的构造器,通过new关键字或者像调用函数那样调用

void main() {
  var p1 = new Person();
  var p2 = Person.fillName("六只脚");
  var p3 = Person.fiiAge(age: 23);
}

常量构造器,当你构造的对象不会被改变时,可以使用常量构造器,在构造器前面加上const关键字修饰,当一个类声明了一个常量构造器,则不能存在非常量构造器,并且这个类中的实例属性必须声明为常量属性,且必须在声明或者实例化时被初始化。当使用const调用常量构造器时,如果参数相同,则为同一实例对象。

void main() {
  var p = const Person(23);
  var p2 = const Person(23);
  var p3 = const Person(27);
  var p4 = Person(23);
  var p5 = Person(23);
  print(p == p2);    //true
  print(p == p3);    //false    
  print(p == p4);    //false
  print(p4 == p5);    //false
}
class Person {
  final int age;
  const Person(this.age);
  static Person person = const Person(18);    
}

通过runtimeType属性来获取实例对象的类型

var p = Person();
print(p.runtimeType); //Person

重定向构造器,重新定向到该类的另一个构造器

class Dog {
  String name;
  int age;
  Dog(this.name, this.age);
  //重定向到该类的主构造器,主构造器指与类名相同的构造器,当然,也可以定向到其它构造器
  Dog.fillName(String name) : this(name, 23); 
}

工厂构造器,通过factory关键字来声明,如果创建的对象相同,则不需要重新创建,直接从缓存的返回对象(工厂构造器里不能使用this关键字)

main() {
  Dog d = Dog("six");
  Dog d1 = Dog("six");
  print(d == d1); //true
  d.name = "leg";
  print(d1.name); //leg
}

class Dog {
  String name;
  static final Map<String, Dog> _cache = <String, Dog>{};
  factory Dog(String name) {
    if (_cache.containsKey(name)) {
      return _cache[name];
    } else {
      final dog = Dog.getDog(name);
      _cache[name] = dog;
      return dog;
    }
  }
  Dog.getDog(this.name);
}

④抽象类

使用关键字abstract来修的类称为抽象类,抽象类可以有静态方法,静态属性跟实例方法和实例属性,抽象类的实例方法的方法体可以省略,至于为什么什么后面接口的实现会提到。一般抽象类用来定义接口,抽象类不能被实例化,如果想实例化抽象类,可以使用factory工厂构造器。

abstract class Person {
  int age;
  final String name;
  Person(this.name);
  void say();
  static eat() {}
}

⑤接口的实现

dart的每个类都隐式定义了一个接口(不管是一般类还是抽象类),接口中包含该类的所有实例成员(构造函数不包括),如果你想不在继承的情况下一个类A支持另一个类B的API,则类A可以使用关键字implements来实现B的接口,一个类可以实现一个或多个类的接口。

abstract class Person {
  int age;
  final String name;
  Person(this.name);
  void say();
  static eat() {}
}

class Man implements Person {
  get age => this.age;
  set age(int age) => this.age = age;
  void say() {}
  get name => this.name;
}

注意:当A类实现B类的接口时,A类中必须重写B类中所有实例属性的getter和setter方法,如果属性是final修饰的常量,则只需重写getter方法,实例方法也要被重写。这也是前面提到抽象类的方法体被可以省略的原因,因为抽象类一般是为了定义接口,接口中的方法要被实现的类重写,所以在接口中的实例方法体体也就没有意义。

⑥类的继承

如果你想创建一个子类,请使用关键字extends,子类中会隐式添加一个super属性,super代表父类。继承是单继承的,这与接口实现不同,一个子类只能有一个父类。

子类不能继承父类的构造器,子类的构造器会默认调用父类的无参主构造器(与类同名的构造器),如果子类想调用父类的其它构造器则需手动调用,如果父类不存在这个构造器,则不能调用,子类也不能声明带此参数的构造器。

void main() {
  Man.fill(); //默认调用父类的Person()构造器
}

class Person {
  int age;
  Person();
  Person.fill(this.age) {
    print("super fill");
  }
}

class Man extends Person {
  Man();
  Man.fill();
}

使用冒号:来调用父类构造器,且子类构造器不能简写,可以省略花括号。

class Animal {
  int age;
  Animal();
  Animal.withAge(this.age);
}

class Cat extends Animal {
  Cat(int age) : super.withAge(age);
}

方法的重写,子类可以重写父类的方法,通过super.methodName()调用父类的方法,dart中方法不能重载,这与java不同

class Animal {
  say() {}
}

class Cat extends Animal {
  @override
  say() {
    super.say();
  }
}

⑦mixin,(混入的意思)给一个类添加特征,使用关键字with

class Musician extends Performer with Musical {
  // ···
}

class Maestro extends Person
    with Musical, Aggressive, Demented {
  Maestro(String maestroName) {
    name = maestroName;
    canConduct = true;
  }
}

为了使用mixin,我们必须创建一个继承Object类的类,并且不能声明构造器,使用mixin关键字代替class关键字

mixin Musical {
  bool canPlayPiano = false;
  bool canCompose = false;
  bool canConduct = false;

  void entertainMe() {
    if (canPlayPiano) {
      print('Playing piano');
    } else if (canConduct) {
      print('Waving hands');
    } else {
      print('Humming to self');
    }
  }
}

可以通过关键字on指定mixin只允许哪个类使用

mixin MusicalPerformer on Musician { //只有Musician能使用
  // ···
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
大模型安全评估测试题大模型安全评估测试题关键词库生成内容测试题库应拒答测试题库非拒答测试题大模型安全评估测试题大模型安全评估测试题关键词库生成内容测试题库应拒答测试题库非拒答测试题大模型安全评估测试题大模型安全评估测试题关键词库生成内容测试题库应拒答测试题库非拒答测试题大模型安全评估测试题大模型安全评估测试题关键词库生成内容测试题库应拒答测试题库非拒答测试题大模型安全评估测试题大模型安全评估测试题关键词库生成内容测试题库应拒答测试题库非拒答测试题大模型安全评估测试题大模型安全评估测试题关键词库生成内容测试题库应拒答测试题库非拒答测试题大模型安全评估测试题大模型安全评估测试题关键词库生成内容测试题库应拒答测试题库非拒答测试题大模型安全评估测试题大模型安全评估测试题关键词库生成内容测试题库应拒答测试题库非拒答测试题大模型安全评估测试题大模型安全评估测试题关键词库生成内容测试题库应拒答测试题库非拒答测试题大模型安全评估测试题大模型安全评估测试题关键词库生成内容测试题库应拒答测试题库非拒答测试题大模型安全评估测试题大模型安全评估测试题关键词库生成内容测试题库应拒答测试题库非拒答测试题大模型安全
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值