// 使用class关键字定义一个类
// 类中主要包含了两个部分:
// 属性
// 方法
class Person{
// 定义实例属性
name:string = '顺悟空'
// 在属性前使用static可以定义类属性,类属性就是不需要将Person实例化,就可以直接Person.name访问
// (静态属性)
static age:number = 88888
// 定义方法,也就是个函数
sayHellow(){
}
..............
}
const per = new Person() // 实例属性的意思是只有通过实例化Person,才能通过这个实例访问里面的属性
实例属性可以通过: per.name 访问, 类属性不行; 可以通过per.name = 'tom' 去修改,但是如果前面加上readonly就不可以修改了
类属性通过: Person.age 访问, 实例属性不行
// 调用sayHellow方法的时候,用实例去调用:pre.sayHellow()
// 如果方法sayHellow前面加上了static,就是一个类方法,直接Person.sayHellow()就可以调用
class Dog{
name:string;
age:number
// constructor构造函数,构造函数会在对象创建时调用,在构造函数中,就是当前新建的那个实例,所以我们 可以通过使用this来向新创建的实例中添加属性
constructor(name:string, age:number){
console.log('执行constructor')
// 在实例方法中,this就表示当前的实例
// console.log(this)
this.name = name;
this.age = age
}
bark(){
// 在方法中可以通过this表示调用当前方法的对象
console.log('汪汪汪')
}
}
const dog = new Dog(name:'小黑',age:4)
dog.bark() // 打印出了小黑这个对象
// 定义一个表示猫的类
class Cat{
name:string;
age:number
constructor(name:string, age:number){
this.name = name;
this.age = age
}
sayHellow(){
console.log('喵喵喵')
}
}
const cat = new Cat(name:'猫咪',age:4)
由于上面两个相似度很大,重复代码很多,以下是解决办法:
// 定义一个animal类
class Animal {
// 将两个重复的代码拿进来:
name:string;
age:number
constructor(name:string, age:number){
this.name = name;
this.age = age
}
bark(){
console.log('动物叫声')
}
}
// 加入extends Animal 的意思是使Dog类继承Animal类,此时Animal是父类,Dog是子类,让子类继承父类,使用继承后,子类中将拥有父类所有的方法和属性,如果希望在子类中加入父类没有的属性和方法,直接加就行,如果在子类中添加了和父类一样的方法,子类的方法会覆盖父类的方法
class Dog extends Animal{
run(){
console.log(`this.name`在跑)
}
}
// 加入extends Animal 的意思是使Cat类继承Animal类
class Cat extends Animal{
}
const cat = new Cat(name:'猫咪',age:4)
const dog = new Dog(name:'小黑',age:4)
dog.bark() // 打印出了小黑这个对象
(function (){
class Animal{
name:string;
constructor(name:string){
this.name = name
}
sayHellow(){
console.log('动物在叫')
}
}
class Dog extends Animal{
age:4;
// 如果这里子类也写了constructor构造函数,那就必须在子类的构造函数中调用父类的构造函数:
constructor(name:strung,age:number){
super(name)
this.age= age
}
sayHellow(){
// super表示当前类的父类
super.sayHellow()
}
}
const dog = new Dog(name:'旺财')
dog.sayHellow()
})()
(function (){
// abstract卡头的类是抽象类,抽象类不能用来创建对象,抽象类是专门用来被继承的类,抽象类中可以添加抽象方法
abstract class Animal{
name:string;
constructor(name:string){
this.name = name
}
// 定义一个抽象方法,使用abstract,没有方法体,抽象方法只能定义在抽象类中,子类必须对抽象方法重写, abstract sayHellow(): void;
}
class Dog extends Animal{
// 如果子类中不重写抽象方法,会报错,因为继承的父类是一个抽象类,有抽象类的方法
sayHellow(){
console.log('汪汪汪')
}
}
const dog = new Dog(name:'旺财')
dog.sayHellow()
})()
// 接口用来定义一个类中包含哪些属性和方法,同时接口可以当成类型声明去使用,不同点是:接口声明的类型可以重复多个,像下面的myInterface可以有多个这个接口,接口可以在定义类的时候限制类的结构
interface myInterface{
name:string;
age:number
}
// 接口中的所有属性都不能有实际的值,接口只定义对象的结构,不管实际值,所有的方法都是抽象方法,不能有实际方法
interface myInter{
name:string;
sayHellow():void;
}
// 定义一个类的时候可以使类去实现一个接口
// 先定义一个类:
// implements用MyClass类实现myInter接口
// 实现接口的意思是:使类满足接口的要求
class MyClass implements myInter{
name:string;
constructor(name:string){
this.name = name
}
sayHellow(){
console.log('大家好')
}
}
(function (){
// 定义一个表示人的类
class Person(){
// public模式属性都是public开头
// private私有属性,只能在类内部进行访问,修改
// protected 受包含的属性,只能在当前类和当前类的子类使用,相对于private完全私有,protected可以让当前类的子类去使用
name:string;
age:number
constructor(name:string,age:number){
this.name = name;
this.age = age
}
// 定义一个方法:用来获取name属性
getName(){
return this.name
}
// 定义一个方法:用来修改name属性
setName(val:string){
this.name = val
}
// 上面是传统写法,下面是ts写法
get name(){
return this.name
}
set name(value:string){
this.name = value
}
}
const per = new Person(name:'悟空',age:88888)
per.setName('八戒')
})()