文章目录
面向对象这个概念跟之前我们学 java 时的是一样的,这里只做简单演示,如果觉得不理解,可以查看我之前写的 Java 面向对象简介 ,是个系列文章,相信你可以学到你想学的。
类
//使用class关键字定义一个类
class Person {
//定义实例属性
name: string = '孙悟空';
//readonly表示只读属性,无法修改
//readonly name:string = '孙悟空';
//定义静态属性
static age: number = 18;
//定义方法,如果以 static 修改也变成了静态方法
sayHello(){
console.log("Hello");
}
}
console.log(Person.age);
const person = new Person();
console.log(person.name);
person.sayHello();
构造函数和this
class Dog{
name:string;
age:number;
//构造函数会在对象创建时执行
constructor(name:string,age:number) {
//this表示当前实例
console.log(this);
this.name = name;
this.age = age;
}
bark(){
console.log("汪汪汪");
}
}
const dog = new Dog("小黑",2);
const dog2 = new Dog("小白",3);
console.log(dog);
继承
(function () {
//定义一个表示狗的类
class Animal {
name:string;
age:number;
constructor(name:string,age:number) {
this.name = name;
this.age = age;
}
sayHello(){
console.log("动物在叫");
}
}
//定义一个表示狗的类,使 Dog 继承 Animal
//Animal是父类,Dog是子类
//子类将拥有父类全部属性和方法
class Dog extends Animal{
//子类覆盖父类方法是方法重写
sayHello(){
console.log("汪汪汪");
}
}
//定义一个表示猫的类
class Cat extends Animal{
sayHello(){
console.log("喵喵喵");
}
}
const dog = new Dog("旺财",2);
console.log(dog);
dog.sayHello();
const cat = new Cat("喵喵喵",1);
console.log(cat);
cat.sayHello();
})();
super
(function () {
//定义一个表示狗的类
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();
}
}
const dog = new Dog("旺财", 2);
console.log(dog);
dog.sayHello();
})();
抽象类
之前我们写了父类 Animal,我们只希望它做父类,不希望它被拿去创建对象,就需要用到抽象类
(function () {
//abstract 开头的是抽象类
//抽象类和其他类没区别,只是不能用来创建对象
//抽象类就是用来被继承的类
abstract class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
//定义一个抽象方法
//使用abstract修饰,没有方法体
//抽象方法只能定义在抽象类中,子类必须重写
abstract sayHello():void;
}
class Dog extends Animal {
//如果不重写会报错,强制重写
sayHello() {
console.log("汪汪汪");
}
}
const dog = new Dog("旺财");
console.log(dog);
dog.sayHello();
})();
接口
其实接口和抽象类非常相似,区别有两个:
1、抽象类能有抽象方法也可以有普通方法,而接口中的方法都是抽象方法
2、抽象类使用 extends
继承,接口使用implements
实现
(function () {
/********* 例子 1 *********/
//先演示描述一个对象的类型
type myType = {
name: string,
age: number
};
const obj: myType = {
name: "张三",
age: 23
};
//接口就是用来定义一个类的结构
//用来定义一个类中应该有哪些类型和方法
//也可以当作类型声明来使用,和上边的作用一样
interface myInterface {
name: string;
age: number;
}
//可以声明相同的接口
interface myInterface {
gender: string;
}
//那么这个obj2里边就是上边接口的和
const obj2: myInterface = {
name: "李四",
age: 24,
gender: "男"
}
/********* 例子 2 *********/
//接口可以在定义类的时候限制类的结构
// 接口中所有属性都不能有实际值
//接口只定义对象的结构,而不考虑实际值
//在接口中所有的方法都是抽象方法
interface myInter {
name: string;
sayHello(): void
}
//定义一个类实现一个接口
class MyClass implements myInter{
name: string;
constructor(name:string) {
this.name = name;
}
sayHello(): void {
console.log("hello")
}
}
})();
属性的封装
(function () {
//定义一个表示人的类
class Person {
//TS可以在属性前添加属性修饰符
//public(共有)
//private(私有)可以添加方法,get、set方法
//protect 只能在当前类和当前类的子类中使用
public name: string;
private age:number;
constructor(name: string,age:number) {
this.name = name;
this.age = age;
}
getAge(){
return this.age;
}
setAge(age:number){
//判断年龄是否合法
if(age>=0){
this.age = age;
}
}
}
const person = new Person("孙悟空",18);
//现在的属性都是在对象中设置的,属性可以被任意修改,这样非常不安全
person.name = "八戒";
//所以可以把属性改为private,然后增加get、set方法
person.setAge(20);
console.log(person);
})();
TS 中设置 getter 方法的方式
(function () {
class Person {
private _name: string;
private _age: number;
constructor(_name: string, _age: number) {
this._name = _name;
this._age = _age;
}
//TS 中getter方法
get name() {
return this._name
}
set name(name: string) {
this._name = name;
}
get age() {
return this._age;
}
set age(age: number) {
if (age > 0) {
this._age = age;
}
}
}
const person = new Person("孙悟空", 18);
person.name = "八戒";
person.age = -22;
console.log(person)
})();
可以将属性直接定义在构造函数中
(function () {
class Person {
//可以将属性直接定义在构造函数中
constructor(public name: string, public age: number) {
}
}
const person = new Person("孙悟空", 18);
console.log(person.name);//打印出孙悟空
})();
泛型
function f(a: number): number {
return a;
}
//在定义函数或类时,类型不明确时,可以使用泛型
function f1<T>(a: T): T {
return a;
}
//可以直接调用泛型的函数
f1(10);
f1<string>("10");
//可以有多个泛型
function f2<T, K>(a: T, b: K): T {
console.log(a);
return a;
}
f2<number, string>(123, "a");
//可以限制泛型的类型
interface Inter {
length: number;
}
//T extends Inter表示泛型T必须是Inter的实现类(子类)
function f3<T extends Inter>(a: T): number {
return a.length;
}
f3({length: 10});
class MyClass<T>{
name:T;
constructor(name:T) {
this.name = name;
}
}
const mc = new MyClass<string>("孙悟空");