一、类的简介
- 使用
class
关键字来定义一个类,类中主要包含了两个部分:属性和方法; - 直接定义的属性相当于在
constructor
构造器中用this.
声明的属性,但是没法传参。是实例属性,需要通过对象的实例去访问:
const per = new Person();
per.name
- 使用
static
开头的属性或是静态属性(类属性),可以直接通过类去访问:
Person.age
- 如果方法以
static
开头则方法就是类方法,可以直接通过类去调用; - 属性前带有
readonly
关键字表示一个只读的属性,无法修改;
class Person{
// 定义实例属性
// readonly name: string = '孙悟空';
name = '孙悟空';
// 在属性前使用static关键字可以定义类属性(静态属性)
// static readonly age: number = 18;
// age = 18;
// 定义方法
sayHello(){
console.log('Hello 大家好!');
}
}
const per = new Person();
// Person.age = 20;
console.log(per);
// console.log(per.name, per.age);
// console.log(Person.age);
// console.log(per.name);
// per.name = 'tom';
// console.log(per.name);
// per.sayHello();
// Person.sayHello();
per.sayHello();
二、构造函数、继承、super
-
constructor
被称为构造函数,构造函数会在对象创建时调用; - 继承
extends
是为了复用部分属性和方法,还可以增加和重写:
Dog extends Animal
中
- Animal被称为父类,Dog被称为子类;
- 使用继承后,子类将会拥有父类所有的方法和属性;
- 通过继承可以将多个类中共有的代码写在一个父类中,
这样只需要写一次即可让所有的子类都同时拥有父类中的属性和方法,
如果希望在子类中添加一些父类中没有的属性或方法直接加就行; - 如果在子类中添加了和父类相同的方法,则子类方法会覆盖掉父类的方法。
这种子类覆盖掉父类方法的形式,我们称为方法重写,采用就近原则;
// 定义一个Animal类
class Animal{
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
// this.name = Number(name);
this.age = age;
}
sayHello(){
console.log('动物在叫~');
}
}
// 定义一个表示狗的类
// 使Dog类继承Animal类
class Dog extends Animal{
run(){
console.log(`${this.name}在跑~~~`);
}
sayHello() {
console.log('汪汪汪汪!');
}
}
// 定义一个表示猫的类
// 使Cat类继承Animal类
class Cat extends Animal{
sayHello() {
console.log('喵喵喵喵!');
}
}
const dog = new Dog('旺财', 5);
const cat = new Cat('咪咪', 3);
console.log(dog);
dog.sayHello();
dog.run();
console.log(cat);
cat.sayHello();
- 如果在子类中写了构造函数,在子类构造函数中必须对父类的构造函数
constructor
进行调用super
,调用可以传参; - 在类的方法中
super
就表示当前类的父类,可以通过super
访问父类的方法和属性。
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
sayHello() {
console.log('动物在叫~');
}
}
class Dog extends Animal{
age: number;
constructor(name: string, age: number) {
// 如果在子类中写了构造函数,在子类构造函数中必须对父类的构造函数进行调用
super(name); // 调用父类的构造函数
this.age = age;
}
sayHello() {
// 在类的方法中 super就表示当前类的父类
//super.sayHello();
console.log('汪汪汪汪!');
}
}
const dog = new Dog('旺财', 3);
dog.sayHello();
三、抽象类
- 以
abstract
开头的类是抽象类,抽象类和其他类区别不大,只是不能用来创建对象; - 抽象类就是专门用来被继承的类,抽象类中可以添加抽象方法;
- 抽象方法使用
abstract
开头,没有方法体; - 抽象方法只能定义在抽象类中,子类必须对抽象方法进行重写。
abstract class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
// 定义一个抽象方法
// 抽象方法使用 abstract开头,没有方法体
// 抽象方法只能定义在抽象类中,子类必须对抽象方法进行重写
abstract sayHello():void;
}
class Dog extends Animal{
sayHello() {
console.log('汪汪汪汪!');
}
}
class Cat extends Animal{
sayHello() {
console.log('喵喵喵喵!');
}
}
const dog = new Dog('旺财');
dog.sayHello();
四、接口
- 接口
type
和类型type
声明的区别:
-
type
可以用来描述一个对象的类型,interface
用来定义一个类结构,定义类中应该包含哪些属性和方法; -
type
不能重复声明,interface
可以重复声明,会叠加; -
interface
也可以当成类型声明去使用;
type myType = {
name: string,
age: number
};
interface myInterface {
name: string;
age: number;
}
interface myInterface {
gender: string;
}
const obj: myInterface = {
name: 'sss',
age: 111,
gender: '男'
};
- 用
interface
来定义一个类结构:
-
interface
定义的类结构类似抽象类,但是抽象类的属性和方法可以有实际值,接口中的所有的属性都不能有实际的值,接口只定义对象的结构,而不考虑实际值; - 接口中所有的方法都是抽象方法;
- 定义类时,可以使类去实现一个接口,实现接口就是使类满足接口的要求。
interface myInter{
name: string;
sayHello():void;
}
class MyClass implements myInter{
name: string;
constructor(name: string) {
this.name = name;
}
sayHello(){
console.log('大家好~~');
}
}
五、属性修饰符
TS可以在属性前添加属性的修饰符
-
public
修饰的属性可以在任意位置访问(修改) 默认值; -
private
私有属性,私有属性只能在类内部进行访问(修改),但是可以通过在类中添加方法使得私有属性可以被外部访问;
class Person{
private _name: string;
private _age: number;
constructor(name: string, age: number) {
this._name = name;
this._age = age;
}
/*
* getter方法用来读取属性
* setter方法用来设置属性
* - 它们被称为属性的存取器
* */
// TS中设置getter方法的方式
get name(){
// console.log('get name()执行了!!');
return this._name;
}
set name(value){
this._name = value;
}
get age(){
return this._age;
}
set age(value){
if(value >= 0){
this._age = value
}
}
}
-
protected
受保护的属性,只能在当前类和当前类的子类中访问(修改); -
get
和set
是属性的存取器,因为对象中设置的属性可以任意的被修改,这会导致对象中的数据变得非常不安全。所以可以通过属性存取器加以限制;
class A{
protected num: number;
constructor(num: number) {
this.num = num;
}
}
class B extends A{
test(){
console.log(this.num);
}
}
const b = new B(123);
- 可以直接将属性定义在构造函数中:
class C{
constructor(public name: string, public age: number) {
}
}
const c = new C('xxx', 111);
console.log(c);