zoukankan      html  css  js  c++  java
  • Class(类)分享 第四节

    一、基础

    // es6 普通的一个类
    // 构造函数为实例添加成员,类的所有方法都定义在类的prototype属性,即原型上面。
    class Animal {
      name
      constructor(name, age){
        this.name = name
      }
    	move(distance){
      	console.log(`The speed of ${this.name} is ${distance}m/s`)
      }
    }
    let a = new Animal("Tom")
    console.log(a.move(5))
    
    //ts, 成员,参数,函数返回值加上类型检查,实例加上类类型
    class Animal { // 声明了类的实例的类型
      name: string
      constructor(name: string){
        this.name = name
      }
      move(distance: number): void{
      	console.log(`The speed of ${this.name} is ${distance}m/s`)
      }
    }
    let a: Animal = new Animal("Tom")
    console.log(a.move(5))
    

    二、继承

    使用extends关键字实现继承。子类中如果有构造方法,必须使用super关键字来调用父类的构造函数

    class Animal {
      name: string;
      age: number;
      constructor(name: string, age: number) {
        this.name = name
        this.age = age
      }
      move(distance: number): void {
        console.log(`The speed of ${this.name} is ${distance}m/s`)
      }
    }
    ​
    class Cat extends Animal {
      catkind
      // 子类有构造函数,必须使用super调用父类构造方法
      constructor(name: string, age: number, catkind: string) {
        super(name, age)
        this.catkind = catkind
      }
      // 重写move
      move(distance: number): void {
        console.log("cat walking...");
        super.move(distance)
      }
    }
    ​
    class Dog extends Animal {
      dogkind
      constructor(name: string, age: number, dogkind: string) {
        super(name, age)
        this.dogkind = dogkind
      }
      move(distance: number): void {
        console.log("dog walking...");
        super.move(distance)
      }
    }
    ​
    let cat1: Cat = new Cat("Tom", 5, "persian")
    console.log(`${cat1.name} is ${cat1.age} years old,its kind is ${cat1.catkind} cat`)
    console.log(cat1.move(5))
    ​
    let dog1: Dog = new Dog("jack", 3, "Husky")
    console.log(`${dog1.name} is ${dog1.age} years old,its kind is ${dog1.dogkind} dog`)
    console.log(dog1.move(10))
    

    三、public private 和 protected

    • public:默认所有的成员和方法都是public。修饰的成员和方法是公开的,可以在任何地方被访问到
    • private: 修饰的成员和方法是私有的的,只能在声明它的类的内部被访问, 不允许被实例和子类访问
    • protected:修饰的成员和方法是受保护的,只能在声明它的类和子类的内部被访问, 不允许被实例访问
    // 1. public
    class Animal {
      public name: string;
      public constructor(name: string) {
        this.name = name;
      }
      public move(distance: number): void {
        console.log(`The speed of ${this.name} is ${distance}m/s。`)
      }
    }
    ​
    let cat1 = new Animal("Tom")
    console.log(cat1.name)
    console.log(cat1.move(5))
    ​
    // 2.1 private-成员
    class Animal {
      private name: string;
      public constructor(name: string) {
        this.name = name;
      }
      public move(distance: number): void {
        console.log(`The speed of ${this.name} is ${distance}m/s。`)
      }
    }
    ​
    let cat1 = new Animal('Tom');
    console.log(cat1);
    console.log(cat1.name); // error 实例不能访问
    console.log(cat1.move(85)); // 类内部可以访问
    ​
    ​
    class Cat extends Animal{
      public constructor(name: string){
        super(name);
      }
      public say() {
        console.log(`${this.name} say miao~miao~`);
      }
    } 
    ​
    let cat2 = new Cat('haha');
    console.log(cat2.name) // error 在子类的实例中也不能被访问
    ​
    // 2.2 private-构造函数
    // 构造函数修饰为 private 时,该类不允许被继承或者实例化
    class Animal {
      public name;
      private constructor(name) {
        this.name = name;
      }
    }
    class Cat extends Animal { // error a. 不能被继承
      constructor(name) {
        super(name);
      }
    }
    let cat1 = new Animal('Jack'); // error b. 不能被实例化
    ​
    // 3.1 protected-成员
    class Animal {
      protected name: string;
      public constructor(name: string) {
        this.name = name;
      }
      public move(distance: number): void {
        console.log(`The speed of ${this.name} is ${distance}m/s。`)
      }
    }
    ​
    let cat1 = new Animal('Tom');
    console.log(cat1.move(85)); // 类内部可以访问
    console.log(cat1.name); // error  实例不能访问
    ​
    class Cat extends Animal{
      public constructor(name: string){
        super(name);
      }
      public say() {
          console.log(`${this.name} say miao~miao~`); // 在子类中可以访问
      }
    } 
    let cat2 = new Cat('haha');
    console.log(cat2.say())
    console.log(cat2.name) // error 在子类的实例中也不能被访问
    ​
    // 3.2 protected-构造函数
    // 构造函数修饰为 protected 时,该类只允许被继承
    class Animal {
      public name;
      protected constructor(name) {
        this.name = name;
      }
    }
    class Cat extends Animal {
      constructor(name) {
        super(name);
      }
    }
    ​
    let a = new Animal('Jack'); // error 不能被实例化
    

    四、readonly

    使用readonly关键字将成员设置为只读的。 只读成员必须在声明时或构造函数里被初始化。

    class Animal {
      readonly name: string;
      readonly age: number = 18; // 声明时初始化
      public constructor(name: string) {
        this.name = name;  // 构造函数里初始化
      }
    }
    ​
    let a = new Animal('Jack');
    console.log(a.name); // Jack
    a.name = 'Tom'; // error 只读
    

    注意如果readonly和其他访问修饰符同时存在的话,需要写在其后面。

    class Animal {
      public readonly name: string;
      public constructor(name: string) {
        this.name = name;
      }
    }
    

    五、参数属性

    一般,我们先声明类的成员和构造函数内赋值。通过参数属性,我们将声明和赋值合并起来。

    // 一般
    class Animal {
      public name: string;
      public constructor(name: string) {
        this.name = name;
      }
    }
    let a = new Animal('Jack');
    console.log(a.name); // Jack
    ​
    // 参数属性
    class Animal {
      // public name: string; // 省略
      public constructor(public name: string) {
        // 参数属性,必须有修饰符  public,protected,private或readonly
        // this.name = name;  // 可省略
      }
    }
    let a = new Animal('Jack');
    console.log(a.name); // Jack
    

    六、存取器

    使用 getter 和 setter 可以改变属性的赋值和读取行为。当类成员上定义存取器时,就不能使用正常成员声明

    class Animal {
      // name: string   成员声明
      constructor(name: string) {
        this.name = name;
      }
      get name() {  // 存取器
        return 'Jack';
      }
      set name(value) {
        console.log('setter: ' + value);
      }
    }
    ​
    let a = new Animal('Kitty');
    a.name = 'Tom';
    console.log(a.name);
    

    七、静态属性

    可以通过static定义创建类的静态成员和方法,这些成员和方法存在于类的本身而不是类的实例上。只能通过类名访问,不能被构造函数实例化

    class Animal {
      static firstWord = "hello";
      constructor(public name: string){}
      sayHi(){
        console.log(Animal.firstWord)
      }
      static isAnimal(animal: Animal): void {
        console.log(animal instanceof Animal);
      }
    }
    let a = new Animal("Tom")
    ​
    console.log(Animal.firstWord)
    Animal.isAnimal(a)
    ​
    console.log(a.firstWord) // error, 实例不能访问
    a.isAnimal(a) // error
    a.sayHi()
    

    八、抽象类

    abstract用于定义抽象类和其中的抽象方法。顾名思义,抽象类和抽象方法是对对一些对象的属性和行为进行高度抽象,一般不包含具体实现细节,所以基类使用。所以,抽象类是不允许被实例化的。其次,抽象类中的抽象方法必须被子类实现,因为一般不包含实现细节。

    abstract class Animal {
      name: string;
      constructor(name: string) {
        this.name = name;
      } 
      abstract move(distance: number): void;
    }
    ​
    class Cat extends Animal {
      constructor(name: string) {
        super(name)
      }
      move(distance: number): void { // 必须实现基类的抽象方法
        console.log(`The speed of ${this.name} is ${distance}m/s`)
      }
    }
    ​
    let a = new Animal('Jack'); // error,不允许实例化
    let cat = new Cat('Tom');
    cat.move(5)
    

    九、类和接口

    一般来讲,一个类只能继承自另一个类,有时候不同类之间可以有一些共有的属性和行为,这时候就可以把这些通用属性和方法提取成接口(interfaces),用implements关键字来实现。

    举例,门是一个类,防盗门是它的子类。车也是一个类,车和防盗门都有报警功能,将其提取成一个报警方法。作为一个接口,防盗门和车等都可以实现它。

    interface Alarm {
        alert(): void;
    }
    ​
    class Door {
    }
    ​
    class SecurityDoor extends Door implements Alarm {
        alert() {
            console.log('SecurityDoor alert');
        }
    }
    ​
    class Car implements Alarm {
        alert() {
            console.log('Car alert');
        }
    }
    

    一个类只能继承自一个类,但也可以实现多个接口

    interface Alarm { // 报警
    alert(): void;
    }
    ​
    interface controlDoor {  // 开关门
    openDoor(): void;
    closeDoor(): void;
    }
    ​
    class Car implements Alarm, controlDoor {
    alert() {
    console.log('Car alert');
    }
    openDoor() {
    console.log('Car door open');
    }
    closeDoor() {
    console.log('Car door close');
    }
    }
    

    类定义会创建两个东西:类的实例类型和一个构造函数。 因为类可以创建出类型,所以你能够在允许使用接口的地方使用类。

    class Point {
        x: number;
        y: number;
    }
    interface Point3d extends Point { // 类可以被当作接口使用
        z: number;
    }
    let point3d: Point3d = {x: 1, y: 2, z: 3};
    
  • 相关阅读:
    Ubuntu 系统下载
    Shell 变量自增实现方法
    shell 单引号以及双引号
    A look at WeChat security
    利用HTTP Cache来优化网站
    require.js 简洁入门
    Nginx rewrite URL examples with and without redirect address
    页面制作部分之PS切图
    Joda-Time 简介
    [官方摘要]Setup And Configuration memcached with Tomcat
  • 原文地址:https://www.cnblogs.com/yxld/p/14042546.html
Copyright © 2011-2022 走看看