OOP – Hướng đối tượng là gì ?

Tram Ho

OOP là gì?

Sau khi bước vào học lập trình một thời gian, chúng ta sẽ tiếp cận với một khái niệm mới và sẽ gây lú với nhiều người đó là OOP – Object Oriented Programming, hay tiếng việt chúng ta gọi là lập trình hướng đối tượng. Nó là một tư duy lập trình với những quy ước hay ý tưởng nhất định giúp cho các chương trình có cấu trúc rõ ràng, dễ bảo trì và mở rộng hơn, chứ nó không phải là một công nghệ của một ngôn ngữ lập trình cụ thể.

Hiện tại đã có rất nhiều bài viết về OOP nhưng chúng ta sẽ thấy phần lớn khá là hàn lâm, trong khi ta nên liên hệ một chút ra thực tế thì sẽ khiến ta hiểu bản chất của chúng hơn rất nhiều. Bài viết này mình muốn chia sẻ kiến thức mình học được, tổng hợp được và đóng góp cho cộng đồng những gì chọn lọc nhất có thể.

Tại sao OOP ?

Đúng rồi đấy, ta nên hiểu theo đúng nghĩa đen của nó – hướng đến một đối tượng cụ thể. Sau khi hiểu về mẫu hình lập trình này, bạn sẽ thấy rằng nếu không có chúng thì chương trình của chúng ta thực sự rất rắc rối đấy. Khi mới học lập trình, code của chúng ta sẽ khá bừa bãi, bạ đâu code đấy mặc dù ta đã sắp xếp theo nhiều module, chia ra hàm hiếc riêng biệt nhưng khi chương trình càng ngày càng lớn hơn thì ta sẽ thấy nó phát sinh ngày càng nhiều vấn đề.

Ví dụ bạn code 1 project mà không theo quy chuẩn nào thì sau một thời gian không động tới liệu chúng ta có thể tiếp tục mở rộng, chỉnh sửa chúng trơn tru luôn không hay lại mất một thời gian tìm hiểu lại, hoặc khi đưa code cho người khác, liệu họ có thể nhìn ra những gì ta đã làm không? Vì vậy OOP sẽ khiến mọi thứ ngăn nắp hơn, theo quy chuẩn chung và tất nhiên sẽ kéo theo các lợi ích khác, vậy chúng có những gì?

Class và Object

Hãy liên hệ sang thực tế, ta sẽ thấy rằng mỗi chúng ta sẽ có những đặc trưng, hành vi riêng và chung. Ví dụ mình và bạn sẽ có những thứ chung như: 2 chân, 2 tay, đau thì khóc, vui thì cười, hoặc những thứ riêng như: mình có chỉ số IQ là 123, bạn có chỉ số IQ 124, … . Nếu mỗi lần muốn tạo một đối tượng nào đấy mà ta code lần lượt từ đầu đến cuối, thêm từng thuộc tính, hành vi cho nó thì sẽ phải là tốn rất nhiều thời gian, vì vậy mà ta cần một cái khuôn chung, đó là class
Bạn cứ hiểu rằng nó như một khôn mẫu và mỗi lần tạo một object (đối tượng) từ cái khuôn đấy thì mọi sản phẩm đó đều thừa hưởng hết những gì mà class đấy có. Cùng xem ví dụ sau đây.

 

 

Ngoài ra sau này khi mà học sâu hơn, các bạn có thể thấy một số thuộc tính có thể chỉ cho phép đọc hoặc chỉ cho phép ghi, khi đó ta chỉ cần 1 trong 2 getter hoặc setter, hoặc có những dữ liệu chỉ sử dụng trong class đấy thôi chỉ chả cần getter hay setter. Nếu như trong một class có thuộc tính mà có thể sử dụng như public, nhưng lại có thuộc tính cần private thì chúng ta vẫn nên cho tất cả chúng là private, sau đó thêm getter, setter, constructor và các method khác. Như vậy sẽ khiến chúng được gọn gàng, đóng gói cẩn thận.

Inheritance – Tính kế thừa

Hãy giả sử rằng bây giờ thị trường Mỹ yêu cầu Porsche làm một dòng Panamera riêng cho thị trường họ, nhưng thêm các tính năng khác là định vị xe, rèm cửa, và một hành vi khác cho xe là báo động. Nếu như chúng ta xây dựng mọi thứ lại từ đầu thì sẽ mất nhiều thời gian, đôi lúc còn bỏ sót thứ gì đấy. Vì vậy mà tính kế thừa được ra đời – nó cho phép một class được thừa hưởng các thuộc tính và hành vi từ class khác, khiến code của chúng ta dễ dàng bảo trì, tái sử dụng hơn.

Từ ví dụ trên, ta sẽ tạo một class kế thừa như sau:

 

 

 

 

Như bạn thấy thì một class con thừa sẻ thừa hưởng hết những gì class cha có, và có thể tùy biến theo của thằng con qua @Override trên kia, xe ở Mỹ nó không thích kêu “Wroom Wroom” nữa nên nó đổi sang “Br Br” là được, còn nó thêm gì của riêng nó thì tự nó thêm như phương thức còi báo động alarmSiren(), hay các thuộc tính khác. Vậy ta đã thấy rằng tính kế thừa này khiến code của chúng ta dễ tái sử dụng, bảo trì hơn. Tại sao lại dễ bảo trì hơn? tại vì nếu như ông Porsche này muốn thêm sửa gì cho tất cả các dòng Panamera thì ổng chỉ cần sửa trong class PorschePanamera là xong.

Polymorphism – tính đa hình

Tính đa hình cho phép các đối tượng cùng kiểu có thể có các hành vi khác nhau. Nó cho phép ta định nghĩa các phương thức có cùng tên nhưng có các hành vi khác nhau cho các lớp con khác nhau. Hãy giả sử bây giờ lại đến Ấn Độ bắt Porsche tạo cho họ một dòng Panamera riêng cho họ, nhưng chỉ thay đổi tiếng của nó thôi:

 

 

 

 

Bây giờ, tại một triển lãm xe có 1 chiếc Panamera bản quốc tế, 1 chiếc bản Mỹ, 1 chiếc bản Ấn và cả 3 chiếc khởi động cùng lúc:

 

 

 

 

Vậy là bạn thấy đấy, 3 chiếc xe cùng có một hành động là khởi động xe, nhưng chúng lại cho ra các kết quả khác nhau. Ta sẽ sang một ví dụ khác của tính đa hình:

 

 

 

 

Abstraction – tính trừu tượng

Tính chất này sẽ giúp chúng ta chỉ xây dựng những gì bề ngoài nó có chứ chẳng quan tâm bên trong nó hoạt động như thế nào, chúng ta sử dụng trừu tượng để giảm sự phức tạp của chương trình và tạo ra một cấu trúc rõ ràng. Tính trừu tượng được thể hiện thông qua các abstract class, interfaceabstract method . Nói như vậy thực ra vẫn hơi mơ hồ nên ta sẽ đến ví dụ.

 

 

 

 

Như các bạn thấy, ở đây chúng ta có abstract class Shape, có các abstract methods là area() và perimeter() và chúng hoàn toàn không có thân, vì vậy chúng ta mới nói rằng tính trừu tượng tức là nó chỉ quan tâm tới bề ngoài mà chẳng biết nó hoạt động như thế nào cả. Bởi vì trong ví dụ này, nếu ta sinh ra các class con extends abstract class Shape thì khi đó ta mới quan tâm tới phần bên trong của nó, ví dụ ta có thêm class biểu trưng cho hình thoi, hình chữ nhật, hình vuông và tất nhiên chúng có các công thức tính chu vi và diện tích khác nhau rồi, vậy nên khi đó ta mới tính tới cách hoạt động của chúng, trong khi abstract chỉ biết rằng mỗi hình đề có chu vi và diện tích.

Nếu như mà chúng ta định nghĩa luôn từ class cha thì chỉ có if else đến ch** mà thôi :U . Trong khi nếu không dùng abstract method thì khi ta xây dựng một class con nào đấy mà ta lại quên một hành vi thì khi đó fix bug rất mệt, vì vậy mà khi extends từ abstract class, hay implement từ interface thì ta đều bắt buộc Override lại hết abstract method.

Ngoài ra, chúng ta cũng nên phân biệt giữa interfaceabstract class, chúng được sử dụng trong những hoàn cảnh khác nhau nhưng đều có chung ý tưởng về tính trừu tượng.


Tóm lại, chúng ta có 4 tính chất chính của OOP như ở trên và chúng ta cũng nên tìm hiểu nhiều nguồn khác nhau để hiểu hơn về chúng, tất nhiên phải có chọn lọc bởi hiện nay thông tin quá nhiều và đôi khi nguồn mơ hồ sẽ khiến ta hiểu nhầm. Thank you all !

Chia sẻ bài viết ngay

Nguồn bài viết : Viblo