TypeScript 面向对象编程 - 封装
大家好! 这里我们仍然在谈论面向对象编程,今天我想介绍一下封装,通过这个 OOP 关键概念,我们将在构建类时掌握一些关键概念。
什么是封装
封装是将数据绑定为类属性,将方法绑定为行为函数的能力,换句话说,封装是通过方法将数据构建和操作到一个单元中的行为。
那好吧!我们又来了!这似乎有点难以理解,但它比你想象的要容易。
这是来自 W3Schools 的一个很好的定义:
Encapsulation 的含义是确保对用户隐藏“敏感”数据。为此,你必须将类变量/属性声明为私有(不能从类外部访问)。如果你希望其他人读取或修改私有成员的值,则可以提供公共的 get 和 set 方法。
所以考虑到这个观点,我们可以找出一些代码并举例说明,我认为我们仍然可以使用我们上次介绍的苏打水机,使用 TypeScript 进行面向对象编程 - 抽象。
我们将发布一项新功能,使我们的机器能够销售啤酒,询问客户姓名和年龄,如果客户未满 18 岁并试图购买啤酒,则必须拒绝交易,否则应继续购买。
考虑到所呈现的特性,让我们开始添加新的属性,也就是类属性,在这种情况下,clientName
为字符串,clientAge
为数字,isAlcoholic
为布尔值。`
/**
* Friendly enum for Soda Flavours
*/
enum ESodaFlavours {
COCA,
LEMON,
ORANGE
}
/**
* The soda fountain machine class
*/
class SodaMachine {
public clientName: string
private clientAge: number
private isAlcoholic: boolean
/**
*
* @param {string} clientName - The Client name
* @param {number} clientAge - The Client age
* @param {boolean} isAlcoholic - 检查要求的饮料是否含酒精
*/
constructor(clientName: string, clientAge: number, isAlcoholic?: boolean) {
this.clientName = clientName
this.clientAge = clientAge
this.isAlcoholic = isAlcoholic || false
}
/**
* Returns the soda when pushed
*/
dropSoda(flavour: ESodaFlavours) {
console.log(`get your soda flavour ${ESodaFlavours[flavour]}`)
console.log(this.isAlcoholic)
}
/**
* Drops ice cubes when pushed
*/
dropIce() {
console.log(`get your ice cubes`)
}
}
const sodaGabriel = new SodaMachine('Gabriel', 50, true)
const sodaJohn = new SodaMachine('John Doe', 16)
sodaGabriel.dropSoda(0)
sodaGabriel.dropIce()
console.log(sodaGabriel.clientName)
sodaJohn.dropSoda(1)
L#15、L#16 和 L#17 — 声明类属性 L#25 - 设置类构造函数,当你实例化你的类时,它作为一个总是执行的方法 L#48, L#49 — 实例化 sodaMachine 类,这一次初始属性为 clientName clientAge 和 isAlcoholic L#54 — 打印客户端名称
将 clientName
值保持为公开允许访问此敏感数据,并且鉴于“确保敏感数据对用户隐藏”,保持公开不是一个好主意,所以让我们将 L#15 从 public clientName: string
更改为 private clientName: string
Getter 和 Setter
这在封装类时非常重要,通过它们你可以为你的类属性写入和读取值,所以 getter 是只读的,setter 是只写的,两者都是提供访问的公共方法 到你的类属性,所以让我们实现它们:
/**
* Friendly enum for Soda Flavours
*/
enum ESodaFlavours {
COCA,
LEMON,
ORANGE
}
/**
* The soda fountain machine class
*/
class SodaMachine {
private clientName: string
private clientAge: number
private isAlcoholic: boolean
/**
*
* @param {string} clientName - The Client name
* @param {number} clientAge - The Client age
* @param {boolean} isAlcoholic - Check if the requested drink is alcoholic
*/
constructor(clientName: string, clientAge: number, isAlcoholic?: boolean) {
this.clientName = clientName
this.clientAge = clientAge
this.isAlcoholic = isAlcoholic || false
}
/**
* Sets the client name
* @param {string} clientName - The Client name
*/
public setClientName(clientName: string) {
this.clientName = clientName;
}
/**
* Sets the client age
* @param {string} clientAge - The Client name
*/
public setClientAge(clientAge: number) {
this.clientAge = clientAge;
}
/**
* Gets the client name
* @returns the current clientName
*/
public getClientName(): string {
return this.clientName
}
/**
* Gets the client name
* @returns the current clientName
*/
public getClientAge(): number {
return this.clientAge
}
/**
* Returns the soda when pushed
* @param flavour - The soda flavour as {@link ESodaFlavours} enum item
*/
dropSoda(flavour: ESodaFlavours) {
console.log(`get your soda flavour ${ESodaFlavours[flavour]}`)
console.log(this.isAlcoholic)
}
/**
* Drops ice cubes when pushed
*/
dropIce() {
console.log(`get your ice cubes`)
}
}
const sodaGabriel = new SodaMachine('Gabriel', 50, true)
const sodaJohn = new SodaMachine('John Doe', 16)
sodaGabriel.dropSoda(0)
sodaGabriel.dropIce()
console.log(sodaGabriel.getClientName())
sodaJohn.dropSoda(1)
console.log(sodaJohn.getClientName())
L#15 — 将类属性 clientName 从 public 移动到 private 限制外部访问 L#35 和 L#43 — clientName 和 clientAge 的设置器 L#51 和 L#59 — clientName 和 clientAge 的 Getter L#87 和 L#90 — 使用 get 方法打印客户端名称
请记住:通常 getter 方法以“get”开头,setter 以 set 开头,后跟变量名,在这两种方法中,变量名称的第一个字母应大写。
使用 setter,我们可以轻松地更改对象属性值,在这种情况下,我想更改客户端名称,我从 John 开始,但应该是 Mark,那么我应该怎么做才能修复它? 也许创建一个新的purchase,如:
/** Marks's purchase*/
const sodaMark = new SodaMachine('sodaMark', 26)
sodaMark.dropSoda(0)
sodaMark.dropIce()
console.log(sodaMark.getClientName())
或者更好的是,我们可以使用我们的 setter 方法,例如:
const sodaGabriel = new SodaMachine('Gabriel', 50, true)
const sodaJohn = new SodaMachine('John Doe', 16)
/** Gabriel's purchase*/
sodaGabriel.dropSoda(0)
sodaGabriel.dropIce()
console.log(sodaGabriel.getClientName())
/** John's purchase*/
sodaJohn.dropSoda(1)
console.log(sodaJohn.getClientName())
sodaJohn.setClientName("Mark")
console.log(sodaJohn.getClientName())
所以现在我们确切地知道如何使用 getter 和 setter,我们终于可以实现我们的新功能了:
/**
* Friendly enum for Soda Flavours
*/
enum ESodaFlavours {
COCA,
LEMON,
ORANGE
}
/**
* The soda fountain machine class
*/
class SodaMachine {
private clientName: string
private clientAge: number
private isAlcoholic: boolean
/**
*
* @param {string} clientName - The Client name
* @param {number} clientAge - The Client age
* @param {boolean} isAlcoholic - Check if the requested drink is alcoholic
*/
constructor(clientName: string, clientAge: number, isAlcoholic?: boolean) {
this.clientName = clientName
this.clientAge = clientAge
this.isAlcoholic = isAlcoholic || false
}
/**
* Sets the client name
* @param {string} clientName - The Client name
*/
public setClientName(clientName: string) {
this.clientName = clientName;
}
/**
* Sets the client age
* @param {string} clientAge - The Client name
*/
public setClientAge(clientAge: number) {
this.clientAge = clientAge;
}
/**
* Gets the client name
* @returns the current clientName
*/
public getClientName(): string {
return this.clientName
}
/**
* Gets the client name
* @returns the current clientName
*/
public getClientAge(): number {
return this.clientAge
}
/**
* Returns the soda when pushed
* @param flavour - The soda flavour as {@link ESodaFlavours} enum item
*/
dropSoda(flavour: ESodaFlavours): void {
if (this.clientAge < 18 && this.isAlcoholic) {
console.log(`Sorry ${this.clientName}, you're ${this.clientAge}, so you're not able to get this drink`)
} else if (this.clientAge >= 18 && this.isAlcoholic) {
console.log(`Hey ${this.clientName}, here's your beer`)
} else {
console.log(`Hey ${this.clientName}, get your soda flavour ${ESodaFlavours[flavour]}`)
}
}
/**
* Drops ice cubes when pushed
*/
dropIce(): void {
console.log(`get your ice cubes`)
}
}
const beerGabriel = new SodaMachine('Gabriel', 50, true)
const sodaJohn = new SodaMachine('John Doe', 16)
const beerTony = new SodaMachine('Tony', 14, true)
/** Gabriel's purchase*/
beerGabriel.dropSoda(0)
beerGabriel.dropIce()
console.log(beerGabriel.getClientName())
/** John's - Mark purchase*/
sodaJohn.dropSoda(1)
console.log(sodaJohn.getClientName())
sodaJohn.setClientName("Mark")
console.log(sodaJohn.getClientName())
/** Tony's purchase */
beerTony.dropSoda(0)
太好了! 我们做到了! 考虑到“敏感数据对用户是隐藏的”,我们为 SodaMachine
增加了新的功能,很好地利用了封装。
相关文章
在 AngularJs 中设置 Select From Typescript 的默认选项值
发布时间:2023/04/14 浏览次数:78 分类:Angular
-
本教程提供了在 AngularJs 中从 TypeScript 中设置 HTML 标记选择的默认选项的解释性解决方案。
在 Angular 中使用 TypeScript 的 getElementById 替换
发布时间:2023/04/14 浏览次数:153 分类:Angular
-
本教程指南提供了有关使用 TypeScript 在 Angular 中替换 document.getElementById 的简要说明。这也提供了在 Angular 中 getElementById 的最佳方法。
在 TypeScript 中使用 try..catch..finally 处理异常
发布时间:2023/03/19 浏览次数:181 分类:TypeScript
-
本文详细介绍了如何在 TypeScript 中使用 try..catch..finally 进行异常处理,并附有示例。
在 TypeScript 中使用 declare 关键字
发布时间:2023/03/19 浏览次数:97 分类:TypeScript
-
本教程指南通过特定的实现和编码示例深入了解了 TypeScript 中 declare 关键字的用途。
在 TypeScript 中 get 和 set
发布时间:2023/03/19 浏览次数:172 分类:TypeScript
-
本篇文章演示了类的 get 和 set 属性以及如何在 TypeScript 中实现它。
在 TypeScript 中格式化日期和时间
发布时间:2023/03/19 浏览次数:161 分类:TypeScript
-
本教程介绍内置对象 Date() 并讨论在 Typescript 中获取、设置和格式化日期和时间的各种方法。
在 TypeScript 中返回一个 Promise
发布时间:2023/03/19 浏览次数:182 分类:TypeScript
-
本教程讨论如何在 TypeScript 中返回正确的 Promise。这将提供 TypeScript 中 Returns Promise 的完整编码示例,并完整演示每个步骤。
在 TypeScript 中定义函数回调的类型
发布时间:2023/03/19 浏览次数:221 分类:TypeScript
-
本教程说明了在 TypeScript 中为函数回调定义类型的解决方案。为了程序员的方便和方便,实施了不同的编码实践指南。
在 TypeScript 中把 JSON 对象转换为一个类
发布时间:2023/03/19 浏览次数:110 分类:TypeScript
-
本教程演示了如何将 JSON 对象转换为 TypeScript 中的类。