美文网首页
06——类

06——类

作者: 转移到CSDN名字丹丹的小跟班 | 来源:发表于2021-04-07 16:29 被阅读0次

    类的定义

    class 类名 {
      类型 成员名;
      返回值类型 方法名(参数列表) {
        方法体
      }
    }
    

    定义一个简单的“人”类

    class Person {
      String name = "张三";
      int age = 20;
      void getInfo() {
        print('我的名字是:${name},我今年${age}');
      }
    }
    
    void main(List<String> args) {
      Person p1 = Person();
      p1.getInfo(); //我的名字是:张三,我今年20
    }
    

    类里面的this指向
    在任何语言里面this指向都是一个比较头疼的问题,但是在dart类里,官方却并不推荐经常使用this,dart建议只有在两种情况下使用this。
    类里面的new
    在dart里面,官方建议为了减少代码迁移时的痛苦, Dart 语言仍允许使用 new 关键字, 但请考在你的代码中弃用和删除 new 。

    • 其中一种情况是要访问的局部变量和成员变量命名一样的时候:
    class Person {
      String name = "张三";
      int age = 20;
      void getInfo() {
        String name = '李四';
        print('我的名字是:${this.name},我今年${age}');
      }
    }
    
    void main(List<String> args) {
      // Person p1 = new Person();
      Person p1 = Person();
      p1.getInfo(); //我的名字是:张三,我今年20
    }
    
    • 还有一种就是使用了重定向

    类里面肯定少不了构造函数了。
    在dart里面有两种构造函数,一种是默认的构造函数,只能存在一个,可以省略不写,也可以自己定义,自己定义的会覆盖默认的。因为dart语言会自动编写。还有一种是命名构造函数,是自己编写的构造函数,可以写多个。dart里子类不会继承父类的构造函数。

    默认构造函数

    class Person {
      String name = "张三";
      int age = 20;
      Person(name, age) {
        this.name = name;
        this.age = age;
        print("我是默认的构造函数,对属性进行了赋值操作");
      }
      void getInfo() {
        print('我的名字是:${name},我今年${age}');
      }
    }
    
    void main() {
      Person p1 = Person("李四", 21);
      p1.getInfo();
    //我是默认的构造函数,对属性进行了赋值操作
    //我的名字是:李四,我今年21
    }
    

    默认构造函数的语法糖
    dart里面提供了一种对构造函数的语法糖,能够更轻易的进行赋值操作。

    class Person {
      String name = "张三";
      int age = 20;
      Person(this.name, this.age)
      void getInfo() {
        print('我的名字是:${name},我今年${age}');
      }
    }
    
    void main() {
      Person p1 = Person("李四", 21);
      p1.getInfo();
    //我是默认的构造函数,对属性进行了赋值操作
    //我的名字是:李四,我今年21
    }
    

    自定义构造函数

    class Person {
      String name = "张三";
      int age = 20;
      Person(this.name, this.age);
      Person.children(this.name, this.age);
      Person.elderly(this.name, this.age);
      void getInfo() {
        print('我的名字是:${name},我今年${age}');
      }
    }
    
    void main() {
      Person p1 = Person.children("大熊", 12);  
      Person p2 = Person.elderly("鬼谷子", 66);
      p1.getInfo();  //我的名字是:大熊,我今年12
      p2.getInfo();  //我的名字是:鬼谷子,我今年66
    }
    

    初始化列表(Initializer list)
    可以在构造函数体执行之前初始化实例变量。 各参数的初始化用逗号分隔。(在“=”右边不能使用this)

    class Sum {
      int num1 = 0;
      int num2 = 20;
      final num sum;
      Sum(int num1, int num2)
        :num1 = num1,
        num2 = num2,
        sum = num1 + num2;
    }
    
    void main() {
      Sum s1 = Sum(1,2);
      print(s1.sum);  //3
    }
    

    重定向构造方法
    在某些情况下, 我们希望在一个构造方法中去调用另外一个构造方法, 这个时候可以使用重定向构造方法

    class Sum {
      int num1 = 0;
      int num2 = 20;
      final num sum;
      Sum(int num1, int num2)
        :num1 = num1,
        num2 = num2,
        sum = num1 + num2;
      Sum.sum2(int x, int y): this(x, y);
      Sum.sum3(int x, int y): this.sum2(x, y);
    }
    
    void main() {
    //向找到sum3.然后重定向到sum2,最后重定向到sum。
      Sum s1 = Sum.sum3(10, 20);
      print(s1.sum);  //30
    }
    

    常量构造方法
    默认情况下,创建对象时,即使传入相同的参数,创建出来的也不是同一个对象。

    class Point {
      late num x;
      late num y;
      Point(this.x, this.y);
    }
    
    void main() {
      Point p1 = Point(1,2);
      Point p2 = Point(1,2);
      print(identical(p1, p2));  //false
    }
    

    在某些情况下,传入相同值时,我们希望返回同一个对象,这个时候,可以使用常量构造方法。就是在构造方法前加const进行修饰,那么可以保证同一个参数,创建出来的对象是相同的。

    class Point {
      final num x;
      final num y;
      const Point(this.x, this.y);
    }
    
    void main() {
      Point p1 = const Point(1,2);
      Point p2 = const Point(1,2);
      print(identical(p1, p2));  //false
    }
    

    常量注意点:
    注意一:拥有常量构造方法的类中,所有的成员变量必须是final修饰的.
    注意二: 为了可以通过常量构造方法,创建出相同的对象,不再使用 new关键字,而是使用const关键字,如果是将结果赋值给const修饰的标识符时,const可以省略.

    setter和getter
    默认情况下,Dart中类定义的属性是可以直接被外界访问的。

    但是某些情况下,我们希望监控这个类的属性被访问的过程,这个时候就可以使用setter和getter了。

    class Color {
      String color = 'green';
      Color(this.color);
      String get getColor{
        return color;
      }
      void set setColor(String val) {
        color = val;
      } 
    }
    
    void main() {
      Color c1 = Color("red");
      print(c1.getColor);  //red
      c1.setColor = "black";
      print(c1.getColor);  //black
    }
    

    类的继承
    面向对象的其中一大特性就是继承,继承不仅仅可以减少我们的代码量,也是多态的使用前提。

    • Dart中的继承使用extends关键字,子类中使用super来访问父类。
    • 父类中的所有成员变量和方法都会被继承,,但是构造方法除外。
    • 子类可以重写父类的属性和方法,
    • 子类中可以调用父类的构造方法,对某些属性进行初始化:
      1. 子类的构造方法在执行前,将隐含调用父类的无参默认构造方法(没有参数且与类同名的构造方法)。
      2. 如果父类没有无参默认构造方法,则子类的构造方法必须在初始化列表中通过super显式调用父类的某个构造方法。
    class Son extends Father {
      String name;
      Son(String name) : name = name, super(name);
      Money() {
        print("我有100美金");
      }
      getFatherAge() {
        print("父亲今年${age}");
      }
    }
    
    void main() {
      Son s1 = Son('fufu');
      s1.Money();  //我有100美金
      s1.getFatherAge();  //父亲今年50
    }
    

    抽象类
    使用 abstract 修饰符来定义 抽象类 — 抽象类不能实例化。 抽象类通常用来定义接口,以及部分实现。 如果希望抽象类能够被实例化,那么可以通过定义一个工厂构造函数来实现。
    抽象类中一般存在抽象方法。没有方法体只有方法名的就是抽象方法,它一般用于当作一个规范。继承了抽象类子类就必须有抽象类的所有方法。

    abstract class Animal {
      eat();
      run();
    }
    
    class Cat extends Animal {
      @override
      eat() {
        print("🐱喜欢吃草");
      }
    
      @override
      run() {
        print("🐱跑起来并不快");
      }
    }
    
    main() {
      Cat c1 = Cat();
      c1.eat(); //🐱喜欢吃草
      c1.run(); //🐱跑起来并不快
    }
    

    注意
    注意一:抽象类不能实例化.
    注意二:抽象类中的抽象方法必须被子类实现, 抽象类中的已经被实现方法, 可以不被子类重写.

    隐式接口
    Dart中每个类都隐式的定义了一个包含所有实例成员的接口,并且这个类实现了这个接口,如果我们需要A类支持B类的方法的话,我们可以选择继承,但是我们可能不想继承B类,或者已经继承了其他类,我们可以选择实现B类隐式接口。在实际开发中,我们通常使用抽象类作为接口。因为接口与继承抽象类相似,都需要重写被调用方法的所有属性和方法。

    abstract class Animal {
      eat();
      run();
    }
    
    class Cat implements Animal {
      @override
      eat() {
        print("🐱喜欢吃草");
      }
    
      @override
      run() {
        print("🐱跑起来并不快");
      }
    }
    
    main() {
      Cat c1 = Cat();
      c1.eat(); //🐱喜欢吃草
      c1.run(); //🐱跑起来并不快
    }
    

    Mixin混入
    如果想要一个类的某个方法,用接口的话需要重写类里的所有属性方法,用继承又只能继承一个类,dart不支持多继承,那么这个时候可以使用Mixin混入。
    dart中新支持了一个类的特性,即为mixins(混入),按照dart官方的说明,这个混入的特性,可以同时混入多个类的属性和方法,使用混入只需要在类上使用with关键字,并可以混入多个。(注意混入与接口不能一起使用,但是可以与继承一起使用)

    class Runner {
      run() {
        print('在奔跑');
      }
    }
    
    class Flyer {
      fly() {
        print('在飞翔');
      }
    }
    class Cat extends Runner with Flyer{
      
    }
    
    main() {
      Cat c1 = Cat();
      c1.fly(); //在飞翔
      c1.run(); //在奔跑
    }
    

    类成员和方法
    使用 static 关键字实现类范围的变量和方法。也就是我们常说的静态方法和静态属性。

    • 静态方法(类方法)不能在实例上使用,因此它们不能访问 this
    class Animal {
      static String name = '动物';
      String color = 'red';
      static void type() {
        print(Animal.name);
      }
      run() {
        print("${Animal.name}在奔跑");
      }
    }
    
    void main() {
      Animal a1 = Animal();
      a1.run();  //动物在奔跑
      print(Animal.name);//动物
      Animal.type(); //动物
    }
    

    注意
    静态成员不能访问非静态成员( static 关键字修饰的成员 不能访问 非 static 关键字修饰的成员)
    非静态成员可以访问静态成员

    枚举类型
    枚举类型也称为 enumerations 或 enums , 是一种特殊的类,用于表示数量固定的常量值。

    enum Color { red, green, blue }
    main(List<String> args) {
      // 枚举中的每个值都有一个 index getter 方法, 该方法返回值所在枚举类型定义中的位置(从 0 开始)。 
      // 例如,第一个枚举值的索引是 0 , 第二个枚举值的索引是 1。
      print(Color.red.index);  //0
      print(Color.green.index);  //1
      List<Color> colors = Color.values;
      print(colors);  //[Color.red, Color.green, Color.blue]
    }
    

    注意
    枚举不能被子类化,混合或实现。
    枚举不能被显式实例化。

    相关文章

      网友评论

          本文标题:06——类

          本文链接:https://www.haomeiwen.com/subject/gxgdkltx.html