TS学习02 面向对象 类、封装继承、接口、泛型

TS学习02

  • TypeScript 面向对象
  • 1、类(class)
    • 属性
      • 实例属性&类属性
      • 只读属性
    • 方法
      • 实例方法
      • 类方法
    • 构造函数 & this
  • 2、面向对象的特点
    • 封装
      • 属性的权限
      • 属性存取器
      • 静态属性
    • 继承
      • 重写
      • super
      • 抽象类
  • 3、接口(Interface)
  • 4、泛型(Generic)
  • 5、练习(没看)
  • 5、练习(没看)

TypeScript 面向对象

BV1Xy4y1v7S2学习笔记

  • 举例来说:
    • 操作浏览器要使用window对象
    • 操作网页要使用document对象
    • 操作控制台要使用console对象

一切操作都要通过对象,也就是所谓的面向对象

什么是对象?计算机程序的本质就是对现实事物的抽象,抽象的反义词是具体,比如:照片是对一个具体的人的抽象,汽车模型是对具体汽车的抽象等等。程序也是对事物的抽象,在程序中我们可以表示一个人、一条狗、一把枪、一颗子弹等等所有的事物。一个事物到了程序中就变成了一个对象。

在程序中所有的对象都被分成了两个部分:数据和功能,以人为例,人的姓名、性别、年龄、身高、体重等属于数据,人可以说话、走路、吃饭、睡觉这些属于人的功能。数据在对象中被成为属性,而功能就被称为方法。所以简而言之,在程序中一切皆是对象。

1、类(class)

要想面向对象,操作对象,首先便要拥有对象,那么下一个问题就是如何创建对象。

要创建对象,必须要先定义类,所谓的类可以理解为对象的模型,程序中可以根据类创建指定类型的对象,举例来说:可以通过Person类来创建人的对象,通过Dog类创建狗的对象,通过Car类来创建汽车的对象,不同的类可以用来创建不同的对象。

  • 定义类:

    class 类名 {属性名: 类型;constructor(参数: 类型){this.属性名 = 参数;}方法名(){....}}
    
  • 示例:

    class Person{name: string;age: number;constructor(name: string, age: number){this.name = name;this.age = age;}sayHello(){console.log(`大家好,我是${this.name}`);}
    }
    
  • 使用类:

    const p = new Person('孙悟空', 18);
    p.sayHello();
    

属性

实例属性&类属性

实例属性:name、age属性本身是存放在 类的示例中的,只有new了之后才可以访问

class Person {name:string = '孙悟空';age: number = 18;
}
const per = new Person();
console.log(per)
console.log(per.name)

类属性/静态属性(在属性前使用static关键字):通过类直接访问,不需要创建实例

class Person {name:string = '孙悟空';static age: number = 18;
}
console.log(Person.age)

只读属性

加上 readonly

class Person {readonly name:string = '孙悟空';age: number = 18;
}

方法

实例方法

class Person {sayHello() {console.log('你好')}
}const per = new Person()
per.sayHello()

类方法

如果方法以static开头则方法就是类方法,可以直接通过类去调用

class Person {static sayHello() {console.log('你好')}
}Person.sayHello()

构造函数 & this

constructor 被称为构造函数,构造函数会在对象创建时调用

在实例方法中,this就表示当前当前的实例,在构造函数中当前对象就是当前新建的那个对象,可以通过this向新建的对象中添加属性

class Dog{name: string;age: number;constructor(name: string, age: number) {this.name = name;this.age = age;}bark(){// alert('汪汪汪!');// 在方法中可以通过this来表示当前调用方法的对象console.log(this.name);}
}const dog = new Dog('小黑', 4);
const dog2 = new Dog('小白', 2);// console.log(dog);
// console.log(dog2);dog2.bark();

2、面向对象的特点

封装

对象实质上就是属性和方法的容器,它的主要作用就是存储属性和方法,这就是所谓的封装

属性的权限

默认情况下,对象的属性是可以任意的修改的,为了确保数据的安全性,在TS中可以对属性的权限进行设置

  • 只读属性(readonly)

如果在声明属性时添加一个readonly,则属性便成了只读属性无法修改

  • TS中属性具有三种修饰符

public(默认值),可以在类、子类和对象中修改

protected ,可以在类、子类中修改

private ,可以在类中修改

示例:

public

class Person{public name: string; // 写或什么都不写都是publicpublic age: number;constructor(name: string, age: number){this.name = name; // 可以在类中修改this.age = age;}sayHello(){console.log(`大家好,我是${this.name}`);}
}class Employee extends Person{constructor(name: string, age: number){super(name, age);this.name = name; //子类中可以修改}
}const p = new Person('孙悟空', 18);
p.name = '猪八戒';// 可以通过对象修改

protected

class Person{protected name: string;protected age: number;constructor(name: string, age: number){this.name = name; // 可以修改this.age = age;}sayHello(){console.log(`大家好,我是${this.name}`);}
}class Employee extends Person{constructor(name: string, age: number){super(name, age);this.name = name; //子类中可以修改}
}const p = new Person('孙悟空', 18);
p.name = '猪八戒';// 不能修改

private:

class Person{private name: string;private age: number;constructor(name: string, age: number){this.name = name; // 可以修改this.age = age;}sayHello(){console.log(`大家好,我是${this.name}`);}// 定义方法 用来获取name属性getName() {return this.name}// 定义方法 设置name属性setName(value: string) {this.name = value}
}class Employee extends Person{constructor(name: string, age: number){super(name, age);this.name = name; //代码错误:子类中不能修改}
}const p = new Person('孙悟空', 18);
p.name = '猪八戒'; // 不能更改
p.setName('猪八戒') //在设置了 getter setter 之后就可以更改

属性存取器

对于一些不希望被任意修改的属性,可以将其设置为private。直接将其设置为private将导致无法再通过对象修改其中的属性。

我们可以在类中定义一组读取、设置属性的方法,这种对属性读取或设置的属性被称为属性的存取器。读取属性的方法叫做setter方法,设置属性的方法叫做getter方法。

示例:TS中有独有的 get set

class Person{private _name: string;constructor(name: string){this._name = name;}// TS中 设置getter方法的方式get name(){return this._name;}// TS中 设置setter方法的方式set name(name: string){this._name = name;}}const p1 = new Person('孙悟空');
console.log(p1.name); // 通过getter读取name属性
p1.name = '猪八戒'; // 通过setter修改name属性

静态属性

  • 静态属性(方法),也称为类属性。使用静态属性无需创建实例,通过类即可直接使用

  • 静态属性(方法)使用static开头

  • 示例:

    class Tools{static PI = 3.1415926;static sum(num1: number, num2: number){return num1 + num2}
    }console.log(Tools.PI);
    console.log(Tools.sum(123, 456));
    
  • this

    • 在类中,使用this表示当前对象

继承

继承是面向对象中的一个特性

使用继承后,子类将会拥有父类所有的方法和属性

通过继承可以将多个类中共有的代码写在一个父类中,这样只需要写一次即可让所有的子类都同时拥有父类中的属性和方法

示例:

Animal被称为父类、Dog和Cat为子类

class Animal{name: string;age: number;constructor(name: string, age: number){this.name = name;this.age = age;}
}class Dog extends Animal{bark(){console.log(`${this.name}在汪汪叫!`);}
}class Cat extends Animal{miaomiao(){console.log(`${this.name}在喵喵叫!`);}
}const dog = new Dog('旺财', 4);
dog.bark();
const cat = new Cat('小花', 5);
dog.miaomiao();

通过继承可以在不修改类的情况下完成对类的扩展

重写

发生继承时,如果子类中添加了和父类相同的方法,就会替换掉父类中的同名方法,这就称为方法的重写

示例:

class Animal{name: string;age: number;constructor(name: string, age: number){this.name = name;this.age = age;}run(){console.log(`父类中的run方法!`);}
}class Dog extends Animal{bark(){console.log(`${this.name}在汪汪叫!`);}// 重写父类的方法run(){console.log(`子类中的run方法,会重写父类中的run方法!`);}
}const dog = new Dog('旺财', 4);
dog.bark();

super

父类也成为超类(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(); 调用父类的sayHelloconsole.log('汪汪汪汪!');}}const dog = new Dog('旺财', 3);
dog.sayHello();

抽象类

(abstract class)

以abstract开头的类是抽象类,

抽象类是专门用来被其他类所继承的类,它只能被其他类所继承不能用来创建实例。

抽象类中可以添加抽象方法。使用abstract开头的方法叫做抽象方法**,抽象方法没有方法体只能定义在抽象类中 ,继承抽象类时抽象方法必须要实现**。

abstract class Animal{abstract run(): void;bark(){console.log('动物在叫~');}
}// 继承抽象类
class Dog extends Animals{// 实现抽象方法run(){console.log('狗在跑~');}
}

3、接口(Interface)

  • 引入
type myType = {name: string,age: number
};const obj : myType = {name: 'sss',age: 111
};

myType是我自己定义的类型,用来限制对象里的属性。也可以使用接口来限制。

概念

接口的作用类似于抽象类,不同点在于接口中的所有方法和属性都是没有实值的,换句话说接口中的所有方法都是抽象方法。

接口主要负责定义一个类的结构,接口可以去限制一个对象的接口,对象只有包含接口中定义的所有属性和方法时才能匹配接口。

同时,可以让一个类去实现接口,实现接口时类中要保护接口中的所有属性。

type myType = {name: string,age: number
};interface myInterface {name: string;age: number;
}const obj : myInterface = { // 对照上文myInterface直接替换myTypename: 'sss',age: 111
};

接口可以在定义类的时候去限制类的结构,接口中的所有的属性都不能有实际的值。接口只定义对象的结构,而不考虑实际值,在接口中所有的方法都是抽象方法。

定义类时,可以使类去实现一个接口。实现接口就是使类满足接口的要求

interface myInter {name: string;sayHello():void;
}class MyClass implements myInter {name:string;constructor(name:string){this.name = name}sayHello():void {alert('大家好')}
}

接口就是定义了一个规范。

接口和抽象类的不同点:① 一个extends 一个implements ② 抽象类有普通方法和抽象方法;接口只有抽象方法

示例(检查对象类型):

interface Person{name: string;sayHello():void;
}function fn(per: Person){per.sayHello();
}fn({name:'孙悟空', sayHello() {console.log(`Hello, 我是 ${this.name}`)}});

示例(实现)

interface Person{name: string;sayHello():void;
}class Student implements Person{constructor(public name: string) {}sayHello() {console.log('大家好,我是'+this.name);}
}

4、泛型(Generic)

定义一个函数或类时,有些情况下无法确定其中要使用的具体类型(返回值、参数、属性的类型不能确定),此时泛型便能够发挥作用。

举个例子:

function fn(a: any): any{return a;
}

上例中,test函数有一个参数类型不确定,但是能确定的时其返回值的类型和参数的类型是相同的,由于类型不确定所以参数和返回值均使用了any,但是很明显这样做是不合适的,首先使用any会关闭TS的类型检查,其次这样设置也不能体现出参数和返回值是相同的类型

在定义函数或是类的时候,如果遇到类型不明确就可以使用泛型

使用泛型:

function fn<T>(a: T): T{return a;
}

这里的<T>就是泛型,T是我们给这个类型起的名字(不一定非叫T,function fn<K>(a: K)K也可以),设置泛型后即可在函数中使用T来表示该类型。所以泛型其实很好理解,就表示某个类型。

那么如何使用上边的函数呢?

  • 方式一(直接使用):
fn(10)

使用时可以直接传递参数使用,类型会由TS自动推断出来,但有时编译器无法自动推断时还需要使用下面的方式

  • 方式二(指定类型):
fn<number>(10)

也可以在函数后手动指定泛型

可以同时指定多个泛型,泛型间使用逗号隔开:

function fn<T, K>(a: T, b: K): K{return b;
}fn<number, string>(10, "hello");

使用泛型时,完全可以将泛型当成是一个普通的类去使用

类中同样可以使用泛型:

class MyClass<T>{prop: T;constructor(prop: T){this.prop = prop;}
}const mc = new MyClass<string>('孙悟空')

除此之外,也可以对泛型的范围进行约束

interface MyInter{length: number;
}function test<T extends MyInter>(arg: T): number{return arg.length;
}test('123')

使用T extends MyInter表示泛型T必须是MyInter的子类,不一定非要使用接口类和抽象类同样适用。

5、练习(没看)

动推断时还需要使用下面的方式

  • 方式二(指定类型):
fn<number>(10)

也可以在函数后手动指定泛型

可以同时指定多个泛型,泛型间使用逗号隔开:

function fn<T, K>(a: T, b: K): K{return b;
}fn<number, string>(10, "hello");

使用泛型时,完全可以将泛型当成是一个普通的类去使用

类中同样可以使用泛型:

class MyClass<T>{prop: T;constructor(prop: T){this.prop = prop;}
}const mc = new MyClass<string>('孙悟空')

除此之外,也可以对泛型的范围进行约束

interface MyInter{length: number;
}function test<T extends MyInter>(arg: T): number{return arg.length;
}test('123')

使用T extends MyInter表示泛型T必须是MyInter的子类,不一定非要使用接口类和抽象类同样适用。

5、练习(没看)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/786044.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

吴恩达机器学习笔记 三十二 K-means初始化 选择聚类数量

K-means 初始化 首先 K < m&#xff0c;若集群的数量多于样本数显然是不合理的。 第一步&#xff1a;随机选取 K 个样本&#xff1b; 第二步&#xff1a;设这 K 个样本为 μ1 μ2 ... μk 有时候K-meas 算法会出现局部最小值的情况&#xff0c;如左下图和右下图&#xf…

spark sql执行引擎原理及配置

如果我们想要给上层开发人员配置好一个统一的sql开发界面&#xff0c;让他们统一通过sql开发即可&#xff0c;可通过spark中的thriftserver服务实现&#xff0c;与hive中的thriftserver类似&#xff0c;配置好该服务后&#xff0c;上层通过db client或者代码中通过jdbc连接即可…

Android U user+root实现方案

背景 由于项目&#xff08;MTK平台&#xff09;上要实现userroot的版本&#xff0c;供特殊用户使用。Android T上的方案无效&#xff0c;经历了各种搜索查看资料&#xff0c;和bsp大佬一起通宵奋战&#xff0c;整出了方案。梳理记录下&#xff0c;有需要的同学可以参考。 Root…

cesium键盘控制相机位置和姿态

该类主要用于监听键盘事件并在用户按下不同按键时执行相应的相机操作&#xff0c;如改变相机的位置、偏航角、俯仰角和翻滚角&#xff0c;从而实现在三维场景中的漫游。 以下是代码的主要逻辑&#xff1a; 导入Cesium库&#xff0c;并定义一个flags对象&#xff0c;其中包含了…

Linux gcc day2

mkdir -p 递归的创建目录 rm or rmdir&#xff1a; rmdir &#xff1a;是用来删除空目录的 实际上我们更加常用的是rm命令 rm可以删除普通文件,也可以删除目录&#xff0c;目录是从某次开始就是一棵树就是递归&#xff0c;所以就要递归删除 rm -r [文件名] 递归删除目录或者目…

linux系统命令chkconfig详解,管理系统服务的工具-查看、启用、禁用和设置系统服务的启动级别

目录 一、chkconfig命令介绍 二、命令的主要作用 1、管理服务的启动和停止&#xff1a; 2、配置运行级别&#xff1a; 3、简化系统管理&#xff1a; 4、查看服务状态&#xff1a; 三、命令语法 1、基本语法 2、运行级别 四、获取帮助 1、通过help获取 2、通过man获…

Azure入门实践-如何创建两个虚拟网络的对等连接

在Azure中创建两个虚拟网络&#xff08;Virtual Network, VNet&#xff09;之间的对等连接&#xff08;VNet Peering&#xff09;可以让这两个虚拟网络中的资源像在同一个网络中一样相互通信。以下是详细的步骤&#xff1a; 1. 登录到Azure门户 打开浏览器&#xff0c;访问Az…

基于“遥感+”蓝碳储量估算、红树林信息提取实践技术应用与科研论文写作

原文链接&#xff1a;基于“遥感”蓝碳储量估算、红树林信息提取实践技术应用与科研论文写作https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247599633&idx5&sn1398cde523f9c5e036e4d478fc1d3388&chksmfa8207f6cdf58ee0a3a2bf652e7ac5cf65636b05f9e3306…

备战蓝桥杯Day36 - 动态规划 - 三角形最小路径和问题

一、什么是动态规划 通过拆分问题&#xff0c;定义问题状态和状态之间的关系&#xff0c;使得问题能够以递推的方式解决。 哪些问题可以使用动态规划&#xff1f; 1、具有最优子结构&#xff1a;问题的最优解所包含的子结构的解也是最优的 2、具有无后效性&#xff1a;未来…

java项目依赖的依赖加载不到

1、描述&#xff1a; 一个项目包含多个子模块&#xff0c;并且可以根据profiles切换环境。 然后依赖的依赖就是加载不到 上面flow-es-6.8是我封装的一个环境。 2、解决: profiles里要加上默认一个环境配置,如下红色部分&#xff1a; 虽然我在idea右边maven中的profiles选项…

【ElementUI】详细分析DatePicker 日期选择器

目录 前言1. 通用Demo2. 快捷键3. 参数 前言 对于全栈玩家&#xff0c;各个组件都需相应了解才可做好前后端的CRUD 以下为实战结合Element官网的心得体会 如图所示&#xff1a; 1. 通用Demo 如果只想要一个选择日期&#xff0c;而不是范围&#xff0c;Demo如下&#xff1a;…

Docker搭建LNMP环境实战(09):安装mariadb

1、编写mariadb部署配置文件 在文件夹&#xff1a;/mnt/hgfs/dockers/test_site/compose下创建文件&#xff1a;test_site_mariadb.yml&#xff0c;内容如下&#xff1a; version: "3.5" services:test_site_mariadb:container_name: test_site_mariadbimage: mari…

逐步学习Go-Select多路复用

概述 这里又有多路复用&#xff0c;但是Go中的这个多路复用不同于网络中的多路复用。在Go里&#xff0c;select用于同时等待多个通信操作&#xff08;即多个channel的发送或接收操作&#xff09;。Go中的channel可以参考我的文章&#xff1a;逐步学习Go-并发通道chan(channel)…

JS基本类型作用域作用域链

#### 作用域链 作用域链的用途&#xff0c;是保证对执行环境有权访问的所有变量和函数的有序访问。看一个例子 js var a 1 function fn () {var b a 1console.log(b) } fn() ### 从代码执行来看 首先在创建fn函数时&#xff0c;会创建一个预先包含全局变量对象的作用域链&am…

Gparted工具 初始化磁盘

Gparted工具 初始化磁盘 1、安装 没有此工具请先安装&#xff1a; yum install epel-release yum install gparted yum install yum-utils git gnome-common gcc-c yum-builddep gparted 2、打开Gparted工具&#xff0c;初始化磁盘 使用具有root权限的普通用户打开gparted&…

HWOD:整型数组排序

一、知识点 while(1){}表示永久循环 使用break结束循环 二、题目 1、描述 输入整型数组和排序标识&#xff0c;对其元素按照升序或降序进行排序 2、数据范围 1<n<1000 0<val<100000 3、输入 第一行输入数组元素个数 第二行输入待排序的数组&#x…

电商技术揭秘二:电商平台推荐系统的实现与优化

文章目录 一、推荐系统的重要性1.1 提升用户体验1.1.1 个性化推荐增强用户满意度1.1.2 减少用户选择困难 1.2 增加销售额1.2.1 促进交叉销售和捆绑销售1.2.2 提高用户购买转化率 1.3 数据分析与用户行为理解1.3.1 挖掘用户偏好和购买习惯1.3.2 为产品开发和库存管理提供数据支持…

npm ERR! code CERT_HAS_EXPIRED 淘宝镜像失效

近期vue安装失败&#xff0c;具体如下&#xff1a; 1.先npm cache clean --force 再下载 插件后缀加上 --legacy-peer-deps 2.certificate has expired npm ERR! code CERT_HAS_EXPIRED npm ERR! errno CERT_HAS_EXPIRED npm ERR! request to https://registry.npm.taobao.o…

rollup 插件的使用及常用插件介绍

rollup 插件的使用及常用插件介绍 如果我们需要打包更为复杂的代码&#xff0c;就需要配置一些插件来实现。比如导入使用 NPM 安装的模块、使用 Babel 编译代码、处理 JSON 文件等等。 插件使用 rollup 是用于打包 JavaScript 的工具&#xff0c;如果我们想处理其他文件&…

Windows安装禅道系统结合Cpolar实现公网访问内网BUG管理服务

文章目录 前言1. 本地安装配置BUG管理系统2. 内网穿透2.1 安装cpolar内网穿透2.2 创建隧道映射本地服务3. 测试公网远程访问4. 配置固定二级子域名4.1 保留一个二级子域名5.1 配置二级子域名6. 使用固定二级子域名远程 前言 BUG管理软件,作为软件测试工程师的必备工具之一。在…