一、類的簡介
- 使用
class關(guān)鍵字來定義一個類,類中主要包含了兩個部分:屬性和方法; - 直接定義的屬性相當(dāng)于在
constructor構(gòu)造器中用this.聲明的屬性,但是沒法傳參。是實例屬性,需要通過對象的實例去訪問:
const per = new Person();
per.name
- 使用
static開頭的屬性或是靜態(tài)屬性(類屬性),可以直接通過類去訪問:
Person.age
- 如果方法以
static開頭則方法就是類方法,可以直接通過類去調(diào)用; - 屬性前帶有
readonly關(guān)鍵字表示一個只讀的屬性,無法修改;
class Person{
// 定義實例屬性
// readonly name: string = '孫悟空';
name = '孫悟空';
// 在屬性前使用static關(guān)鍵字可以定義類屬性(靜態(tài)屬性)
// 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();
二、構(gòu)造函數(shù)、繼承、super
-
constructor被稱為構(gòu)造函數(shù),構(gòu)造函數(shù)會在對象創(chuàng)建時調(diào)用; - 繼承
extends是為了復(fù)用部分屬性和方法,還可以增加和重寫:
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();
- 如果在子類中寫了構(gòu)造函數(shù),在子類構(gòu)造函數(shù)中必須對父類的構(gòu)造函數(shù)
constructor進行調(diào)用super,調(diào)用可以傳參; - 在類的方法中
super就表示當(dāng)前類的父類,可以通過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) {
// 如果在子類中寫了構(gòu)造函數(shù),在子類構(gòu)造函數(shù)中必須對父類的構(gòu)造函數(shù)進行調(diào)用
super(name); // 調(diào)用父類的構(gòu)造函數(shù)
this.age = age;
}
sayHello() {
// 在類的方法中 super就表示當(dāng)前類的父類
//super.sayHello();
console.log('汪汪汪汪!');
}
}
const dog = new Dog('旺財', 3);
dog.sayHello();
三、抽象類
- 以
abstract開頭的類是抽象類,抽象類和其他類區(qū)別不大,只是不能用來創(chuàng)建對象; - 抽象類就是專門用來被繼承的類,抽象類中可以添加抽象方法;
- 抽象方法使用
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聲明的區(qū)別:
-
type可以用來描述一個對象的類型,interface用來定義一個類結(jié)構(gòu),定義類中應(yīng)該包含哪些屬性和方法; -
type不能重復(fù)聲明,interface可以重復(fù)聲明,會疊加; -
interface也可以當(dāng)成類型聲明去使用;
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來定義一個類結(jié)構(gòu):
-
interface定義的類結(jié)構(gòu)類似抽象類,但是抽象類的屬性和方法可以有實際值,接口中的所有的屬性都不能有實際的值,接口只定義對象的結(jié)構(gòu),而不考慮實際值; - 接口中所有的方法都是抽象方法;
- 定義類時,可以使類去實現(xiàn)一個接口,實現(xiàn)接口就是使類滿足接口的要求。
interface myInter{
name: string;
sayHello():void;
}
class MyClass implements myInter{
name: string;
constructor(name: string) {
this.name = name;
}
sayHello(){
console.log('大家好~~');
}
}
五、屬性修飾符
TS可以在屬性前添加屬性的修飾符
-
public修飾的屬性可以在任意位置訪問(修改) 默認值; -
private私有屬性,私有屬性只能在類內(nèi)部進行訪問(修改),但是可以通過在類中添加方法使得私有屬性可以被外部訪問;
class Person{
private _name: string;
private _age: number;
constructor(name: string, age: number) {
this._name = name;
this._age = age;
}
/*
* getter方法用來讀取屬性
* setter方法用來設(shè)置屬性
* - 它們被稱為屬性的存取器
* */
// TS中設(shè)置getter方法的方式
get name(){
// console.log('get name()執(zhí)行了??!');
return this._name;
}
set name(value){
this._name = value;
}
get age(){
return this._age;
}
set age(value){
if(value >= 0){
this._age = value
}
}
}
-
protected受保護的屬性,只能在當(dāng)前類和當(dāng)前類的子類中訪問(修改); -
get和set是屬性的存取器,因為對象中設(shè)置的屬性可以任意的被修改,這會導(dǎo)致對象中的數(shù)據(jù)變得非常不安全。所以可以通過屬性存取器加以限制;
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);
- 可以直接將屬性定義在構(gòu)造函數(shù)中:
class C{
constructor(public name: string, public age: number) {
}
}
const c = new C('xxx', 111);
console.log(c);