使用 TypeScript 进行面向对象编程

2025-06-07

使用 TypeScript 进行面向对象编程

嘿,Dev

这周过得怎么样?希望大家过得愉快。今天的教程让我们一起学习面向对象编程 (OOP)。

面向对象编程 (OOP) 是一种依赖于类和对象概念的编程范式。它用于将软件程序构建为简单、可重用的代码蓝图(通常称为类),这些代码蓝图用于创建对象的单个实例。

对象编程非常适合大型、复杂且积极更新或维护的程序。

Object 类是 JavaScript 的一种数据类型。它用于存储各种键值对集合以及更复杂的实体。对象可以通过 Object() 构造函数或对象初始化器/字面量语法创建。

下面是一个对象类的示例。在这个例子中,我们定义了一个 Person 对象,它具有一些属性和一个方法。



// person class
class Person {
   name: string = '' // default
   age: number = 0 // default 

   greetings(){
     return this.name + ' ' + this.age
   }
}

// to create a new instance of a class
const person1: any = new Person()
person1.name = 'Kevin Odongo'
person1.age = 36 
console.log(person1.greetings()) // This should render Kevin Odongo 36


Enter fullscreen mode Exit fullscreen mode

面向对象编程的好处

面向对象编程的一些好处如下:

  1. 更容易调试
  2. 通过继承重用代码
  3. 通过多态性实现灵活性
  4. 有效解决问题
  5. 项目解耦(将项目分成几组)

让这一天变得美好

面向对象编程原则

封装。

每个对象的实现和状态都私有地保存在一个定义的边界或类内。其他对象无权访问此类,也无权进行更改,但只能调用一系列公共函数或方法。这种数据隐藏特性可以提高程序安全性,并避免意外的数据损坏。

请看这个例子。在这个例子中,我们定义了两个对象类,并分别创建了它们的实例。因此,用外行人的话来说,封装原则规定,motor1的新实例不能访问person1的属性。如果你尝试访问,应该会收到这样的警告。

类型“Motor”上不存在属性“age”



// person object
class Person {
   name: string = ''
   age: number = 0
}

// motor vehicle object
class Motor {
  make: string = ''
  model: string = ''
  color: string = ''
}

// create a new instance of each
const person1 = new Person()
const motor1 = new Motor()

// warning Property 'age' does not exist on type 'Motor'
motor1.age() 


Enter fullscreen mode Exit fullscreen mode

抽象。

对象仅显示与其他对象使用相关的内部机制,隐藏任何不必要的实现代码。这一概念有助于开发人员更轻松地进行后续更改和添加。

这在开发中非常强大,并且 TypeScript 为我们提供了几种操作类对象中成员可见性的方法。

让我们看看这是如何运作的。在这个例子中,我们在所有 Person 属性中添加了 public 属性。默认情况下,所有属性都是 public 的,但为了提高可读性,最好添加 public 属性。



// person class object
class Person {
   public name: string = ''
   public age: string = ''

   public greetings(){
     return name + ' ' + age
   } 
}


Enter fullscreen mode Exit fullscreen mode

我们可以使用以下内容来控制属性可见性:

  • 民众
  • 受保护
  • 私人的
  • 静止的

此外,我们可以使用readonly,这将阻止对构造函数之外的字段进行分配。

让我们再举一个例子来进一步理解这个概念。



// class person

class Person {
   private readonly credentials: string = ''
   private name: string = ''
   private department: string = ''

   constructor(value: string){
      this.credentials = value
   }

   public setName(name: string): void {
      if(!this.credentials) return
      this.name = name
      // logic get department
      const userDepartment = axios.get(.....)
      if(userDepartment) this.department = userDepartment
   }

   public getName(){
     return `Employee name: ${this.name}, Department: ${this.department}`
   }
}


Enter fullscreen mode Exit fullscreen mode

在上面的例子中,如果我们尝试在不提供凭据的情况下创建一个新的 Person 实例,则会收到警告,并且无法编译。首先要注意的是,凭据可见性是private readonly,这意味着它只能在构造函数中更新。



// warining An argument for 'value' was not provided.
const person1 = new Person()

// this will succeed
const person1 = new Person('123456')


Enter fullscreen mode Exit fullscreen mode

还有一件事我们不应该做,那就是我们所有的属性都是私有的,不能在类对象之外访问。请注意,我们只能在类对象之外访问公共对象。

尝试一下



// this will succeed
const person1 = new Person('123456')

person1. // this will automatically list for you all the properties accessible and you will NOTE all the private attributes cannot be accessed outside the class object.


Enter fullscreen mode Exit fullscreen mode

遗产。

对象之间的关系和子类可以分配,从而允许开发人员重用通用逻辑,同时仍保持独特的层次结构。面向对象编程 (OOP) 的这一特性可以进行更彻底的数据分析,缩短开发时间并确保更高的准确性。

看一下这个例子。你会注意到,通过扩展 TeslaCompnany,我们继承了所有公共属性,并且可以在创建 TeslaEmployee 的新实例时调用它们。这让我们可以拥有一个基类,并在不同的子类中重用该基类。



// class company 
type Department = {
   name: string
}

type Employee = {
   name: string
   age: number
}

class TeslaCompany {
      private static role = "Admin"
      private readonly credentials: string = ''
      private departments: (Department)[] = []
      private employees: (Employee)[] = []

      constructor(cred: string) {
        this.credentials = cred
      }

      addDepartment(value: Department) {
        this.departments = [...this.departments, value]
      }

      addEmployee(value: Employee) {
        this.employees = [...this.employees, value]
      }
    }

    class TeslaEmployee extends TeslaCompany {
      private new_employee: Employee = { name: '', age: 0}

      public setName(name: Employee): void {
        this.new_employee = name

      }
}

const newTeslaEmployee = new TeslaEmployee('123456')
newTeslaEmployee.setName({ name: 'Kevin Odongo', age: 36 })
newTeslaEmployee.addDepartment({ name: 'Finance' })
newTeslaEmployee.addEmployee({ name: 'Kevin Odongo', age: 36 })
console.log(newTeslaEmployee)


Enter fullscreen mode Exit fullscreen mode

多态性。

根据上下文,对象可以呈现多种形式。程序会确定对象每次执行所需的含义或用途,从而减少重复代码的需要。

让我们通过一个例子来理解这一点。我们会注意到,Person 对象由两个不同的子类扩展,并且在每个子类的新实例创建时都采用不同的上下文。



// class Person
class Person {
   public name: string = ''
   public role: string = '' 
}

class basketballPlayer extends Person {
     public setName(name: string){
       this.name = name
       this.role = 'BasketBall Player'
    }
    public getName(){
       return `User name: ${this.name} Role: ${this.role}`
    }
}

class golfPlayer extends Person {
    public setName(name: string){
       this.name = name
       this.role = 'Golf Player'
    }
    public getName(){
       return `User name: ${this.name} Role: ${this.role}`
    }
}

const person1 = new basketballPlayer()
const person2 = new golfPlayer()
person1.setName('Kevin Odongo')
person2.setName('Kevin Odongo')
console.log(person1.getName())
console.log(person2.getName())


Enter fullscreen mode Exit fullscreen mode

庆典

恭喜您耐心地讲解了面向对象编程的原理,并通过示例帮助我们理解每个概念。

摘要说明

封装性——类对象处于特定的边界内。例如,一个国家的公民都生活在特定的边界内,并受其法律的管辖。

抽象 - 类对象只能共享公共属性,并隐藏私有属性。这为控制其行为提供了一种绝佳的方式。

继承——我们可以继承其他类并扩展所有公共属性。

多态性——对象可以根据上下文采取各种行为。

除了使用类,我们还可以使用函数。以我们在示例中使用的 Person 类对象为例,我们可以将其定义如下:

选项 1

在此选项中,我们不需要创建 Person 对象的新实例来访问 Person 对象。



// person object
var Person = (function () {
      let user: {
        name: ''
        age: 0
      }

      return {
        setName: function (value: any) {
          user = Object.assign({}, value)
        },

        getName: function (){
          return user
        },

        greetings: function() {
          return `Hello this is ${user.name}`
        }
      }

})()
Person.setName({ name: "Kevin Odongo", age: 36})
console.log(Person.getName())
console.log(Person.greetings())


Enter fullscreen mode Exit fullscreen mode

选项 2

在这个例子中,您会注意到我们正在使用它来访问函数中的用户的属性。



// person object
function Person() {
      const userProfile = {
        user: {
          name: '',
          age: 0,
        },

        setName: function (value: any) {
          this.user = Object.assign({}, value)
        },

        getName: function () {
          return this.user
        },

        greetings: function () {
          return `Hello this is ${this.user.name}`
        }
      }
  return userProfile
}

const person1 = Person()
person1.setName({ name: "Kevin Odongo", age: 36 })
console.log(person1.getName())
console.log(person1.greetings())


Enter fullscreen mode Exit fullscreen mode

我就先到此为止,我们先消化一下,然后在下一个教程中继续讲解。希望这能帮助大家更好地理解使用 TypeScript 进行面向对象编程。

祝您度过愉快的一周!

再见。

文章来源:https://dev.to/kevin_odongo35/object-oriented-programming-with-typescript-574o
PREV
React Icons 在 React 中使用图标的最简单方法
NEXT
具有模块联合的微前端 [第 1 部分] - Vite + React