class类常见知识点的总结

252 阅读6分钟

前言:该篇总结引用uniapp uts语法文档,详细资料请查看uniapp.dcloud.net.cn/tutorial/sy…

类(class)

类声明由类名以及由花括号包围的类体构成。

// 定义Person Class
class Person {
	
}

基本概念

类是对象化的概念,有属性、方法、构造函数

  • 属性:是一个简单的值,可以是字符串、数字、布尔或另一个class。可以用 对象.属性名 的访问,也可以通过 对象.属性名=xxx 的方式赋值。
  • 方法:是一段代码的集合,有入参、有返回值(均可选)。可以用 对象.方法名(参数) 的方式访问。构造函数:用于初始化实例。

下面的示例中,定义了一个 Person 的 class,它有一个属性 name,有一个构造函数 constructor(名称不可改),还有一个方法 getNameLength。

// 定义Person Class
class Person {
	name:string = ""; // 属性name
	constructor(newname:string) { // 构造函数,参数newname
		console.log("开始实例化"); 
		this.name = newname;
	}
	getNameLength():number{ // 方法getNameLength
		return this.name.length
	}
}

定义了class后,需要实例化(通过new关键字)。定义一个实例后,即可使用该实例对象的属性和方法。

一个class可以被多次实例化为不同的实例,互不影响。

//实例化上面定义的class并调用其属性方法
let p = new Person("tom"); // 使用 new 关键字实例化对象时,会自动触发构造函数
console.log(p.name); // 访问p这个对象的属性name,返回值tom
console.log(p.getNameLength()); // 调用p这个对象的方法getNameLength,返回值3

let p2 = new Person("jerry"); // 使用 new 关键字再实例化一个新对象
console.log(p2.name); //jerry
console.log(p2.getNameLength()); //5

构造函数(constructor)

构造函数 constructor ,在创建新对象时(new的时候)会自动执行,用于初始化对象属性。

  • 语法:
constructor([arguments]) { ... }
  • 描述:

你可以不写构造函数。如果没有显式指定构造函数,运行环境会自动添加默认的 constructor 方法。

在一个类中只能有一个名为 “constructor” 的特殊方法。一个类中出现多次构造函数 (constructor)方法将会抛出一个 SyntaxError 错误。

  • 示例:
class Person {
	name:string = "";
	constructor(newname:string) {
		this.name = newname;
	}
}

let person = new Person("tom"); // 使用 new 关键字创建对象时,会自动触发构造函数
console.log(person.name); // tom

在一个构造函数中可以使用 super 关键字来调用一个父类的构造函数

class Polygon {
    constructor() {
        this.name = "Polygon";
    }
}

class Square extends Polygon {
    constructor() {
        super();
    }
}

实例属性

class 有实例属性和静态属性。uts 中实例属性存在于类的每一个实例中。

声明实例属性

在类中声明属性,默认可读,可写。

class Person {
	name:string = ""; // 声明实例属性name
	city:string = "beijing" // 声明实例属性city
	constructor(newname:string) {
		this.name = newname; // 在构造函数中对name重新赋值
	}
}

let person1 = new Person("tom"); // 使用 new 关键字创建对象时,会自动触发构造函数
console.log(person1.name); //tom
console.log(person1.city); //beijing
let person2 = new Person("jerry"); // 使用 new 关键字创建对象时,会自动触发构造函数
console.log(person2.name); //jerry
console.log(person2.city); //beijing

Getter 与 Setter

uts支持通过getter/setter 来截取对对象属性的访问。他可以理解为属性的读取/写入的拦截器

下面的例子中,针对 person对象提供了name的get和set的拦截,paascode不正确时无法修改name的值。

const passcode = "secert passcode"
class Person {
        private _name: string = ""
        get name(): string {
        consolo.log("start to get person.name")
        return this._name;
        }
        set name(newName: string) {
        console.log("start to set person.name")
        if(passcode === "secert passcode") {
            this._name = newName
        }else {
            console.log("Error: set person.name fail")
        }
}
let p = new Person()
p.name = "tom" //会打印"start to set person.name"
console.log(p.name) //会打印"start to get person.name"然后打印tom

readonly

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

class Person {
	readonly name: string;
	readonly age: number = 0;
	constructor (theName: string) {
		this.name = theName;
	}
}
let p = new Person("tom");
console.log(p.name);
p.name = "jerry"; // 错误! name 是只读的
p.age = 1 // 错误! age 是只读的

静态属性(static)

使用关键字 static 来将一个属性声明为静态属性。静态属性不会在实例中被调用,而只会被类本身调用。它们经常是工具函数,比如用来创建或者复制对象

class Person {
	static age:number = 10; // age是静态属性。不能在实例p中访问,但可以通过类Person访问
	getAge():number{
		return Person.age
	}
}
console.log(Person.age); //10
let p = new Person(); //新建一个实例
console.log(p.age); //undefined
console.log(p.getAge()); //10

实例方法

实例方法存在于类的每一个实例中。

声明实例方法

类中声明实例方法。

下面定义一个通过高度乘以宽度计算面积的类。

class Rectangle {
    private height:number;
    private width:number;
    constructor(height: number, width: number) {
        this.height = height;
        this.width = width;
    }
    calcArea(): number {
        return this.height * this.width;
    }
}

使用一个实例方法,以类实例调用它即可:

const square = new Rectangle(10, 10);
square.calcArea(); // 100

继承(extends)

使用继承来扩展现有的类。扩展的子类继承了父类的属性方法,但又可以添加自己独有的属性方法,以及复写父类定义的属性方法。

被继承的类称为父类(也称为超类、基类),新扩展的类称为子类(也称为派生类)。

比如定义了Person类存储人的基本信息,还可以定义一个Developer子类继承自Person类,在子类里追加Developer的独有信息。

  • 语法:
class ChildClass extends ParentClass { ... }
  • 描述:

extends 关键字用来创建一个类的子类。

  • 示例:
// 定义父类
class Person {
	name:string = "";
	constructor(newname:string) {
		this.name = newname;
	}
}
// 定义子类
class Developer extends Person{
	likeLanguage:string = "ts"
}

let d = new Developer("tom"); // 实例化。由于子类没有声明和复写自己的构造函数,所以默认继承了父类的构造函数
console.log(d.name); // tom
console.log(d.likeLanguage); // ts
  • 如果要控制父类中某些属性方法不被子类继承,可使用可见性修饰符(private、protected等)
  • 多重继承:子类还可以被孙类继承

覆盖方法(override)

覆盖,也称为复写、重写。在继承中,用于在子类中改写父类定义的方法或属性。

可覆盖的成员以及覆盖后的成员需要显式修饰符override。

class Polygon {
    name(): string {
        return "Polygon";
    }
}

class Square extends Polygon {
    override name(): string {
        return "Square";
    }
}

Square.name 函数上必须加上 override 修饰符。如果没写,编译器会报错。

覆盖属性

属性与方法的覆盖机制相同。父类中已声明的同名属性,在子类中重新声明必须以 override 开头,并且它们必须具有兼容的类型(都是字符串、或数字、布尔值等)。

class Shape {
     vertexCount: Int = 0
}

class Rectangle extends Shape {
    override  vertexCount = 4
}

调用父类实现

子类中的代码可以使用 super 关键字调用其父类的方法。不能跨级调用父类的父类(爷爷类)的方法。

class Rectangle {
    draw() {}
}
class FilledRectangle extends Rectangle {
    override draw() {
        super.draw();
    }
}

可见性修饰符

类的方法与属性都可以有可见性修饰符。

三个可见性修饰符:private、 protected、 和 public。 默认可见性是 public。

public

自由的访问程序里定义的 public 成员,这也是 uts 的默认行为。

private

当成员被标记成 private 时,它就不能在声明它的类的外部访问。比如:

private

当成员被标记成 private 时,它就不能在声明它的类的外部访问。比如:

class Person {
    private name: string = "Cat";
}

new Person().name; // 错误: 'name' 是私有的.

protected

protected 修饰符与 private 修饰符的行为很相似,但有一点不同,protected 成员在继承的派生类中仍然可以访问。比如:

class Person {
    protected name: string;
    constructor(name: string) {
        this.name = name;
    }
}

class Employee extends Person {
    private department: string;

    constructor(name: string, department: string) {
        super(name);
        this.department = department;
    }

    public getElevatorPitch(): string {
        return `Hello, my name is ${this.name} and I work in ${this.department}.`;
    }
}
const howard = new Employee("Howard", "Sales");
console.log(howard.getElevatorPitch());
console.log(howard.name); // 错误

注意,我们不能在 Person 类外使用 name,但是我们仍然可以通过 Employee 类的实例方法访问,因为 Employee 是由 Person 派生而来的