06.Dart - 类

个人学习用
不严谨
学习的话请看别的博客

使用类的成员

void main() {
  /**
   * Dart 是支持基于 mixin 继承机制的面向对象语言,所有对象都是一个类的实例,而所有的类都继承自 Object 类。基于 mixin 的继承 意味着每个除 Object 类之外的类都只有一个超类,
   * Extension 方法是一种在不更改类或创建子类的情况下向类添加功能的方式。
   *
   * 使用(.)来访问对象的实例变量或方法
   * 使用?.代替 . 可以避免左边的表达式为null而导致的问题
   *
   */
  print(MyClazz.a); //调用静态变量
  MyClazz clazz = new MyClazz();

  clazz.b;
  clazz.showText();
}

class MyClazz {
  static int a = 1;
  int b = 2;

  void showText() {
    print('$a$b');
  }
}

使用构造函数

void main() {
  /**
   * 使用构造函数
   * 命名方式:
   *    类名  或者  类名.标识符 的形式
   *
   *
   */
  var p1 = Paint(1, 2);
  var p2 = Paint.fromJson({"x": 1, "y": 2});
  var p3 = Paint.fromJson({"a": 1, "b": 2});

  p1.showText(); // 1 2
  p2.showText(); // 1 2
  p3.showText(); //null  null ,因为传值时候 键值对不正确,键名字错误,方法键是 xy ,我使用的是 ab
}

class Paint {
  int x;
  int y;

  Paint(this.x, this.y);

  Paint.fromJson(Map<String, int> jsonMap) {
    this.x = jsonMap["x"];
    this.y = jsonMap["y"];
  }

  void showText(){
    print(x);
    print(y);
  }
}

常量构造函数

void main() {
  /**
   *常量构造函数
   * 使用常量构造函数创建对象时,参数一样情况下,创建的对象是一个
   *
   */

  //使用时候要用 const来定义 构造函数

  var p1 = const Porint(1, 2);
  var p2 = const Porint(1, 2);
  var p3 = Porint(1, 2);
  print(p1 == p2); //true
  print(p1 == p3); //false
  print(p2 == p3); //false
}

// 常量构造函数:final定义属性,const定义构造方法
class Porint {
  final int a; //final定义属性
  final int b;

  const Porint(this.a, this.b); //const定义构造方法

  void showText() {
    print('$a$b');
  }
}

获取对象的类型

void main() {
  /**
   * 获取对象类型
   * 使用 对象名.runtimeType来获取运行时对象的类型
   *
   */

  var p1 = Point(1, 2);
  var p2 = Point.fromJson({'x': 3, 'y': 4});
  var p3;
  print(p1.runtimeType);//Point
  print(p2.runtimeType);//Point
  print(p3.runtimeType);//Null
}

class Point {
  int a;
  int b;

  Point(this.a, this.b);

  Point.fromJson(Map<String, int> jsonMap) {
    this.a = jsonMap['x'];
    this.b = jsonMap['y'];
  }

}

实例变量

void main() {
  /**
   * 实例变量
   * 所有实例变量均会隐式地声明一个 Getter 方法,非 final 类型的实例变量还会隐式地声明一个 Setter 方法。
   *
   */
}

class Potin {
  int x; //声明实例变量 x 并初始化为 null。
  int y; //声明实例变量 y 并初始化为 null。
  int z = 0; // 声明实例变量 z 并初始化为 0。
//所有实例变量均会隐式地声明一个 Getter 方法,
// 非 final 类型的实例变量还会隐式地声明一个 Setter 方法。
}

构造函数

void main() {
  /**
   * 构造函数
   */
}

class Point {
  int x;
  int y;

//  Point(this.x, this.y); //构造方法语法糖

  //默认构造函数
  Point(int x, int y) {
    this.x = x;
    this.y = y;
  }

  //命名构造函数
  Point.mingming(int i, int j) {
    this.x = i;
    this.y = j;
  }
}

方法

void main() {
  /**
   * 方法
   */
}

class Point {
  int x, y;

  Point(this.x, this.y);

  int getNum(Point other) {
    return this.x + this.y + other.x + other.y;
  }

  int get getTop => x + y; //get方法

  set setTop(int i) => i - x;//set方法
}

抽象方法

void main() {
  /**
   * 抽象方法
   * 实例方法.Getter方法以及Setter方法都可以是抽象方法
   * 定义一个接口方法而不去做具体的实现让实现他的类去实现该方法
   * 抽象方法只能存在于抽象类中
   *
   */
}

//被abs修饰了,是抽象类
abstract class Father {
  void show(); //没有{} 所以是抽象方法
}

class Son extends Father {
  /**
   * 重写抽象类中的抽象方法
   */
  @override
  void show() {
    print("你好,我是被重写的方法");
  }
}

抽象类

void main(){
  /**
   * 抽象类
   * 1.被abstract修饰的类 为 抽象类,抽象类无法被实例化
   * 2.抽象类常用于声明接口方法,有时也会有具体的实现方法
   * 3.如果想让抽象类可被实例化,可以为抽象类定义 工厂构造函数
   * 4.有抽象方法的类一定是抽象类,抽象类里不一定有抽象方法
   *
   */
}

abstract class Point{
  void show();
}

隐式接口

void main() {
  /**
   * 每一个类都隐式的定义了一个接口并且实现了该接口
   * 这个接口包含: 所有这个类的实例成员  以及这个类所实现的其它接口
   * 如果创建类A支持调用B类的API,但是又不想竭诚B类,则可以实现B类的接口
   *
   * 如果想要实现多个接口,则可以再 class Point implements Comparable, Location {...}
   */
  String getHi(Person person) => person.getString("张三");
  print(getHi(Person("李四"))); //你好,张三,我是李四
  print(getHi(Son())); //你好张三
}

class Person {
  final _name;

  Person(this._name);

  String getString(who) => '你好,$who,我是$_name';
}

class Son implements Person {
  get _name => '我是默认的名字';

  @override
  String getString(String who) {
    return '你好$who';
  }
}

扩展一个类

void main() {
  /**
   * 使用 extend继承来 扩展一个类
   *
   */

  var s = Son(3);
  s.show(); //章金来

  s.showMore(); //章金来  //我今年3岁了
}

class Father {
  String xing;
  String ming;

  Father(this.xing, this.ming);

  void show() {
    print('$xing$ming');
  }
}

class Son extends Father {
  int age;

  Son(this.age) : super('章', '金来');

  /**
   * 重写的show方法
   */
  @override
  void show() {
    super.show();
  }

  void showMore() {
    super.show();
    print('我今年$age岁了');
  }

}

重写操作符

void main() {
  /**
   * 重写操作符: 通过operator方法可以重写 原来的操作符,达到自定义的效果
   * 优先级: 混合运算时候 返回值要匹配,并且优先级不变
   */

  var c1 = CaoZuo(1, 2);
  var c2 = CaoZuo(3, 4);

  print((c1 + c2).x); //4
  print((c1 + c2).y); //-2
  print((c1 - c2).x); //4
  print((c1 - c2).y); //8

}

class CaoZuo {
  int x, y;

  CaoZuo(this.x, this.y);

  //重写 + 操作符
  CaoZuo operator +(CaoZuo other) => CaoZuo(this.x + other.x, this.y - other.y);

  //重写 - 操作符
  CaoZuo operator -(CaoZuo other) {
    CaoZuo caoZuo = new CaoZuo(this.x, this.y);
    caoZuo.x = caoZuo.x + other.x;
    caoZuo.y = caoZuo.y * other.y;
    return caoZuo;
  }
}

Extension扩展

void main() {
  /**
   * Extension 方法 ,扩展,增加的意思
   * 在Dart2.7中引入,为现有的库中添加功能的方法
   * 在 IDE 中使用代码完成功能时,它建议将 Extension 方法与常规方法一起使用
   * 不能对 dynamic使用这样的方法
   *
   *
   *冲突:
      如果扩展成员与接口或其他扩展成员发生冲突,则有几个选项。
      1.更改导入冲突扩展的方式,使用show或hide公开或者隐藏API :
      import 'string_apis_2.dart' hide NumberParsing2;
      2.另一个选项是显式地应用扩展
      NumberToString('111').parseInt()
      3.如果两个扩展名相同,则可能需要使用前缀导入
      import 'string_apis.dart';
      import 'string_apis_3.dart' as rad;  // 使用了前缀  as  red ,前缀名是 red
      print(NumberParsing('42').parseInt());
      print(rad.NumberParsing('42').parseInt());  //前缀的调用方式

   */
  print('42'.parseInt());
  print(NumberToString('111').parseInt()); //显示调用
  dynamic d = '123';
  var v = '123';

  //dynamic定义的数据 会报错
  //dynamic定义的数据 会报错
//  print(d.parseInt());//NoSuchMethodError: Class 'String' has no instance method 'parseInt'.
  print(v.parseInt()); // 不会报错,因为变量v被推断为类型String:
}

/**
 * 使用这个方式把parseInt方法,添加到String中
 */
extension NumberToString on String {
  int parseInt() {
    return int.parse(this);
  }

  double parseDouble() {
    return double.parse(this);
  }
  
}

枚举类型

enum Color { red, green, blue }
//enum 不能再方法内部定义,会报错
void main() {
  /**
   * 枚举类型 Enumerated types
   * 也称为 enumerations 或 enums,用于定义一些固定数量的常量值
   * 每一个枚举值都有一个名为 index 成员变量的 Getter 方法
   */

  print(Color.red.index); //0
  print(Color.green.index); //1
  print(Color.blue.index); //2

  //使用枚举的 values方法 获取到 所有枚举的 值的列表
  List<Color> list = Color.values;
  print(list);

  //可以用在switch语句中
  switch (Color.red) {
    case Color.red:
      break;

    case Color.green:
      break;

    case Color.blue:
      break;
  }

  //枚举的限制:

  //不能成为子类,
  //不能实现枚举
  //不能显式的实例化一个枚举类
  //不能 mixin
}

Mixin模式

void main() {
  /**
   * Mixin 混合模式
   * 使用 with 关键字,可以实现多类似于多继承
   */

  TestSon son = TestSon();
  son.show();
}

//只能 子类实现
class TestSon extends Test with Music {
  show();
}

class Test {}

//定义一个Mixin类,
//1.使用mixin关键字,不能使用class
//2.使用on 关键字,后面跟上 可以 mixin的类,只有继承了Test类的子类才可以使用 whth Music
mixin Music on Test {
  //3.不能定义构造方法
  int x, y, z;

  void show() {
    print('$x$y$z');
  }
}

静态变量和静态方法

void main() {
  /**
   * 静态变量 和  静态方法
   *
   * 静态变量在首次使用的时候被初始化
   * 静态方法不能使用实例来调用,因为静态加入内存比较早,实例比较晚
   * 静态只能访问静态
   */
}

class Point {
  static int i = 1;

  static void show(){
    print(i);
  }
}
发布了33 篇原创文章 · 获赞 6 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/zlhyy666666/article/details/104581205