Lập trình hướng đối tượng với TypeScript

TypeScript là một ngôn ngữ mã nguồn mở miễn phí hiện đang được phát triển và bảo trì bởi Microsoft. Nó là superset của JavaScript, với các bổ sung các tuỳ chọn kiểu tĩnh và lớp trên cơ sở lập trình hướng đối tượng cho ngôn ngữ này. Vì TypeScript là tập cha của JavaScript nên bất kì chương trình JavaScript nào đã có cũng đều là chương trình TypeScript hợp lệ. nhưng hầu hết các trình duyệt chưa hỗ trợ nên cần được biên dịch ra JavaScript để có thể hoạt động. Có 4 tính chất của một ngôn ngữ lập trình hướng đối tượng là tính bao đóng (encapsulation), tính kế thừa(inheritance), tính đa hình(polymorphism), tính trừu tượng(Abstraction) và TypeScript hỗ trợ cả 4 tính chất này một cách rõ ràng và ngắn gọn

1. Tính trừu tượng (Abstraction)

     Lớp trừu tượng là lớp mà từ đó các lớp khác có thể kế thừa được. Không giống như interface, lớp trừu tượng có thể chứa các thuộc tính cũng như các hàm thực thi(các phương thức abstract thì chỉ khai báo chứ không thực thi). Trong TypeScript cũng sự dụng từ khóa abstract để định nghĩa các lớp và phương thức trừu tượng. Chúng ta cùng xét ví dụ ở dưới đây:

abstract class Employee{
   
private name:string;
   
private age:number;
   
private qualification:string;

   
constructor(name:string, age:number, qualification:string){
       
this.name = name;
       
this.age = age;
       
this.qualification = qualification;
   
}
   
abstract applyTheJob():void // phương thức abstract không chứa hàm thực thi
   
abstract mailCheck():void
   
getNameAge(){
        
console.log(this.name + this.age)
    }
   
getQualification(){
       
console.log(this.qualification)
    }
}
Kế thừa từ lớp trừu tượng: các class được kế thừa phải khai báo đầy đủ các phương thức abstract của class cha 
class _employee extends Employee{
   
constructor(name:string, age:number, qualification:string){
       
super(name, age, qualification);
   
}
   
applyTheJob(){
       
console.log('Applying for web developer position')
    }
   
mailCheck(){
       
console.log('Confirm mail before the interview')
    }
}
Abstraction (tính trừu tượng) và encapsulation (tính bao đóng chúng ta sẽ tìm hiểu ngay sau đây) là hai đặc điểm có liên quan nhau trong lập trình hướng đối tượng. Trừu tượng cho phép tạo ra các thông tin không được hiển thị rõ ràng và đóng gói cho phép một người lập trình thể hiện tính trừu tượng ở mức độ mong muốn.

2. Tính bao đóng (Encapsulation):

    Tính bao đóng là tính chất không cho phép cho người dùng hay đối tượng thay đổi dự liệu thành viên của đối tượng nội tại. Chỉ có các hàm thành viên của đối tượng mới có quyền thay đổi trạng thái nội tại đó. Các đối tượng khác muốn thay đổi cần phải truyền một thông điệp cho đối tượng. Việc quyết định có thay đổi hay không vẫn do đối tượng nội tại quyết định
Tính đóng gói là không cho phép bên ngoài biết được bên trong đối tượng có những gì hay logic xử lí như thế nào, nếu muốn thay đổi bên trong đối tượng thi phải được sự chấp nhận của đối tượng đó thông qua các mức độ truy cập private, protected, public

Sau đây là một ví dụ về tính bao đóng:

class Employee{
    private name:string;
    private age:number;
    private qualification:string;
    constructor(name:string, age:number, qualification:string){
        this.name = name;
        this.age = age;
        this.qualification = qualification;
    }
    public getInfo(){
        console.log(`
        Name: ${this.name};
        age: ${this.age};
        Qualification: ${this.qualification}
        `);
    }
}
let _employee = new Employee('NVA',24,'bachelor');

class ScutiCompany{
    public member:number;
    public name:string;
    constructor(name:string){
        this.name = name;
    }
     static getInfoEmployee(){
        return _employee.getInfo();
    }
}
ScutiCompany.getInfoEmployee();
Các thuộc tính trong class Employee để ở trạng thái private và chỉ có thể được lấy ra từ phương thức  public getInfo(), như vậy đối tượng _employee sẽ được đóng gói. Từ đó class company có thể lấy được thông tin đối tượng employee từ phương thức getInfo()

3. Tính kế thừa (Inheritance)

     Nhằm tránh việc khai báo lặp lại các phương thức và thuộc tính, thêm vào đó là thuận tiện trong việc bảo trì và nâng cấp code dễ dàng hơn và giải pháp là tính kế thừa. Tính kế thừa là tính chất rất quan trọng trong lập trình hướng đối tượng. Có thể thể hiện tính kế thừa trong TypeScript một cách dễ dàng qua từ khóa extends :
class Company{
    protected name:string;
    protected member:number;
    constructor(name:string, numberMember:number){
        this.name = name;
        this.member = numberMember;
    }
    public getInformation(){
        console.log(`
         Welcome ${this.name} <br/>
         We have ${this.member} member
        `);
    }
}
class ITcompany extends Company{
    public makeWebsite(nameProject:string){
        console.log('We are making' + nameProject)
    }
    public makeProduct(nameProject:string){
        console.log(`We are developing ${nameProject} our own product `)
    }
}
let Scuti = new ITcompany('Scuti',15);
Scuti.getInformation();
Scuti.makeWebsite('OutSourcing_projects');
Scuti.makeProduct('CookStar');
Có thể dễ dàng nhận thấy class ITcompany thừa kế từ class Company thông qua từ khóa extends, từ đó các phương thức và thuộc tính protected hay public đều được thế hiện ở class ITcompany 

4. Tính đa hình (Polymorphism)

    Tính đa hình trong lập trình hướng đối tượng là sự thay đổi hành vi của phương thức ở mỗi đối tượng khác nhau. Đi đôi với tính kế thừa ta có tính đa hình cũng rất dễ để thể hiện trong TypeScript. Ta cùng xét ví dụ quen thuộc sau sẽ thấy rõ ràng nhất tính đa hình trong OOP:
const PI = 3.14;

class Shape{
    constructor(name:string){}
    protected Perimeter(){}
    protected Acreage(){}
}

class Circle extends Shape{
    private radius:number;
    constructor(name:string,radius:number){
    super(name);
    this.radius = radius;
    }
    Perimeter(){
        let perimeter = 2*PI*this.radius;
        console.log('Perimeter is:' + perimeter);
    }
    Acreage(){
        let acreage = PI*this.radius*this.radius;
        console.log('Acreage is:' + acreage);
    }
}
Bây giờ tiếp tục tạo thêm một class Square kế thừa từ Shape
class Square extends Shape{
    private length:number;
    private width:number;
    constructor(name:string, length:number, width:number){
    super(name);
    this.length = length;
    this.width = width;
    }
    Perimeter(){
        let perimeter = (this.length + this.width)*2;
        console.log('perimeter is :' + perimeter);
    }
    Acreage(){
        let acreage = this.length * this.width;
        console.log('acreage is :' + acreage);
    }
}
let circle = new Circle('hinh tron',6);
circle.Perimeter(); // Perimeter is:37.68
circle.Acreage();   // Acreage is:113.03999999999999
let square = new Square('hinh cn',8,9);
square.Perimeter(); // Perimeter is :34
square.Acreage();   // Acreage is :72
Nhận thấy cùng là một phương thức tính chu vi và diện tích được kế thừa từ class Shape nhưng với các đối tượng khác nhau, thuộc tính khác nhau thì thực thi khác nhau 

Lời kết (conclusion)

TypeScript vẫn đang trong quá trình phát triển. Trong quá trình nguyên cứu TypeScript, tôi chỉ thấy cái khó của nó nằm ở cú pháp mới lạ. Còn về phần tính năng, khái niệm thì khá quen với các ngôn ngữ hướng đối tượng khác như C# hay PHP
Ngoài ra hiện nay rất nhiều thư viện cũng như framework của JavaScipt đã chuyển sang sử dụng cú pháp của TypeScript nên đây sẽ là ngôn ngữ rất đáng để đầu tư trong tương lai

If you liked this article

Let's subscribe the updates of Scuti!
Share on Google Plus

About Anh Tú Vũ

This is a short description in the author block about the author. You edit it by entering text in the "Biographical Info" field in the user admin panel.
    Blogger Comment
    Facebook Comment

0 Comments:

Post a Comment