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

Một điểm mới về mẫu hình, về quan điểm

OOP vẫn còn là một đề tài của nhiều tranh cãi về định nghĩa chuẩn xác hay về các nguyên lý của nó.
Trong dạng tổng quát nhất, OOP được hiểu theo cách là một loại thực nghiệm viết chương trình văn bản được phân cấp ra thành nhiều mô đun (module), mà mỗi mô đun đóng vai như một lớp vỏ che đại diện cho mỗi kiểu dữ liệu.
Những khái niệm liên hệ đã được góp nhặt lại để tạo thành một khuôn khổ cho việc lập trình. Các triết lý đằng sau việc định hướng đối tượng đã trở nên mạnh mẽ để tạo thành một sự chuyển đổi mẫu hình trong ngành lập trình.
Những mẫu hình khác như lập trình chức năng và lập trình thủ tục tập trung chủ yếu trên các hành động, còn lập trình lô gíc lại tập trung vào những khẳng định hợp lý để kích hoạt sự thực thi của mã chương trình.
OOP đã phát triển một cách độc lập từ việc nghiên cứu về các ngôn ngữ định hướng của hệ thống mô phỏng, đó là SIMULA 67, và từ việc nghiên cứu các kiến trúc của hệ thống có độ tin cậy cao, đó là các kiến trúc CPU và khả năng cơ bản của các hệ điều hành.
Một chức năng đặc sắc của OOP là việc xử lý các kiểu con của các kiểu dữ liệu.
Dữ liệu của các đối tượng, một cách tổng quát, được đòi hỏi trong thiết kế để thỏa mãn các yêu cầu của người lập trình (tức là các lớp).
Các kiểu dữ liệu bị giới hạn thêm các điều kiện mặc dù có cùng kiểu dữ liệu với loại không bị ràng buộc bởi các điều kiện đó, gọi là kiểu dữ liệu con. Cả hai loại kiểu dữ liệu này đều dựa vào và đều được điều tiết bởi các hành xử (tức là các phương thức) đã được định nghĩa. Các điều kiện hay yêu cầu này có thể được khai báo rõ ràng hay được giả thiết công nhận ngầm bởi người lập trình. Các ngôn ngữ định hướng đối tượng cung cấp nhiều cơ chế cho việc khẳng định rằng các giả thiết đó có tính địa phương cho một phần của chương trình. Các cơ chế này này có thể đọc thấy trong các tài liệu về các chương trình định hướng đối tượng.
OOP tự nó đã đang được dùng để khuyến mãi cho nhiều sản phẩm và dịch vụ. Các định nghĩa hiện tại và ích lợi của các đặc tính của OOP thường được màu mè hóa bởi các mục đích của thị trường thương mại. Tương tự, nhiều ngôn ngữ lập trình có những quan điểm đặc biệt về OOP mà nó ít tổng quát trong một số khía cạnh.
Các định nghĩa chính xác của OOP sẽ có sự khác biệt tùy theo quan điểm. Đặc biệt, các ngôn ngữ có kiểu tĩnh thường có cái nhìn hơi khác với các ngôn ngữ có kiểu động về OOP, nguyên do là vì chúng tập trung trên thời gian dịch hay tập trung vào thời gian thi hành của các chương trình.
OOP thường được xem là một mẫu hình hơn là một kiểu hay một phong cách lập trình nhằm nhấn mạnh vào điểm quan trọng là OOP có thể thay đổi phương thức phát triển phần mềm bằng cách thay đổi tư duy của những người lập trình và những kỹ sư phần mềm về phần mềm.
Mẫu hình của OOP chủ yếu không phải là kiểu lập trình mà là kiểu thiết kế. Một hệ thống được thiết kế bởi định nghĩa của các đối tượng mà các đối tượng này sẽ tồn tại trong hệ thống đó, trong mã mà hiện làm việc chưa tương thích với đối tượng, hay là trong người dùng đối tượng do ảnh hưởng của tính chất đóng của đối tượng.
Cũng nên lưu ý rằng có sự khác biệt giữa mẫu hình định hướng đối tượng và lý thuyết các hệ thống. OOP tập trung trên các đối tượng như là các đơn vị của một hệ thống, trong khi đó, lý thuyết các hệ thống lại tự nó chỉ tập trung vào hệ thống. Như là phần trung gian, người ta có thể tìm thấy các dạng thức thiết kế phần mềm hay các kỹ thuật khác dùng các lớp và các đối tượng như là các viên gạch trong những thành phần lớn hơn. Những thành phần này có thể được xem như là bước trung gian từ mẫu hình định hướng đối tượng đến các mô hình "định hướng sống thực" hơn của lý thuyết các hệ thống.

Các mẫu hình định hướng đối tượng con

Có nhiều phong cách lập trình hướng đối tượng. Sự khác nhau giữa các phong cách này là tùy theo việc các ngôn ngữ lập trình chú trọng vào khía cạnh nào của sự thuận lợi của định hướng đối tượng và vào việc kết hợp các cấu trúc trong các phương cách khác nhau.

OOP với các ngôn ngữ cấu trúc

Trong các ngôn ngữ cấu trúc, OOP thường xuất hiện như là một dạng mà ở đó các kiểu dữ liệu được mở rộng để hành xử giống như là một kiểu của một đối tượng trong OOP, hoàn toàn tương tự cho một kiểu dữ liệu trừu tượng với sự mở rộng như là sự kế thừa. Mỗi phương pháp thực ra là một chương trình con mà, một cách cú pháp, giới hạn nội trong một lớp.

Các mô hình nguyên mẫu cơ bản

Khác với cách sử dụng lớp, nguyên mẫu là một mô hình khác ít được biết đến hơn, nó có ý nghĩa đạt tới việc chia sẻ ứng xử theo định hướng đối tượng. Sau khi đối tượng được định nghĩa, một đối tượng khác tương tự sẽ được định nghĩa từ đối tượng ban đầu. Ngôn ngữ nguyên mẫu cơ bản được biết đến nhiều nhất là JavaScript mà đây là một sự thiết lập của ECMAScript. Self, một ngôn ngữ lập trình được phát triển bởi Sun Microsystems cũng là một ví dụ của ngôn ngữ dùng nguyên mẫu cho việc chia sẻ ứng xử chứ không dùng sự phân lớp. NewtonScript, Act1, Io và Delegation là các ví dụ khác. Đặc biệt, Hybrid và Exemplars sử dụng cả hai mô hình nguyên mẫu và phân lớp. Trong các hệ thống nguyên mẫu, các đối tượng tự chúng là các khuôn thức (template), trong khi các hệ thống phân lớp dùng các lớp như là các khuôn thức cho các đối tượng.
Các tiếp cận kiểu phân lớp thì chiếm đa số trong OOP mà nhiều người sẽ định nghĩa các đối tượng như là có tính chất đóng mà việc chia sẻ dữ liệu xảy ra bởi sự phân lớp và bởi tính kế thừa. Mặc dù vậy, khái niệm tổng quát hơn "chia sẻ ứng xử" được công nhận như là các kỹ thuật thay thế (như trường hợp nguyên mẫu).
(Xem thêm Lập trình nguyên mẫu cơ bản)

OOP trong văn lệnh

Trong những năm gần đây, lập trình đối tượng cơ bản đã đặc biệt trở nên phổ biến trong các ngôn ngữ lập trình văn lệnh vì chúng có tính trừu tượng, tính đóng, khả năng tái sử dụng, và dễ sử dụng (trong khi khả năng kế thừa trong các ngôn ngữ này vẫn còn là các câu hỏi chưa có câu trả lời). Smalltalk có thể là ngôn ngữ đầu tiên có kiểu như trên, Python và Ruby là các ngôn ngữ tương đối mới và được xây dựng từ đầu với ý tưởng OOP, trong khi đó ngôn ngữ văn lệnh Perl đã đang được từ từ thêm vào các chức năng mới về định hướng đối tượng kể từ phiên bản 5. Khả năng của các đối tượng để thể hiện "thế giới thực" là một lý do cho sự phổ biến của JavaScript và ECMAScript, mà được bàn cãi là thích hợp để đại diện cho DOM của các hồ sơ HTML và XML trên Internet.

Một số khái niệm cần biết trong ngôn ngữ OOP hiện đại

Hiện nay các ngôn ngữ OOP phổ biến nhất đều tập trung theo phương pháp phân lớp trong đó có C++, Java, C# và Visual Basic.NET. Ngôn ngữ OOP hay còn gọi là ngôn ngữ lập trình hướng đối tượng, là một phương pháp thiết kế và phát triển phần mềm dựa trên kiến trúc lớp và đối tượng.
Sau đây là một số khái niệm mà các ngôn ngữ này thường dùng tới

Lớp (class)

Một lớp có thể được hiểu là khuôn mẫu để tạo ra các đối tượng. Trong một lớp, người ta thường dùng các biến để mô tả các thuộc tính và các hàm để mô tả các phương thức của đối tượng. Khi đã định nghĩa được lớp, ta có thể tạo ra các đối tượng từ lớp này. Để việc sử dụng được dễ dàng, thông qua hệ thống hàm tạo (constructor), người ta dùng lớp như một kiểu dữ liệu để tạo ra các đối tượng.

Lớp con (subclass)

Lớp con là một lớp thông thường nhưng có thêm tính chất kế thừa một phần hay toàn bộ các đặc tính của một lớp khác. Lớp chia sẻ sự kế thừa gọi là lớp cha (parent class).
ll

Thuộc tính (attribute)

Thuộc tính của một lớp bao gồm các biến, các hằng, hay tham số nội tại của lớp đó. Ở đây, vai trò quan trọng nhất của các thuộc tính là các biến vì chúng sẽ có thể bị thay đổi trong suốt quá trình hoạt động của một đối tượng. Các thuộc tính có thể được xác định kiểu và kiểu của chúng có thể là các kiểu dữ liệu cổ điển hay đó là một lớp đã định nghĩa từ trước. Như đã ghi, khi một lớp đã được thực thể hoá thành đối tượng cụ thể thì tập hợp các giá trị của các biến nội tại làm thành trạng thái của đối tượng. Giống như trường hợp của phương thức, tùy theo người viết mã, biến nội tại có thể chỉ được dùng bên trong các phương thức của chính lớp đó, có thể cho phép các câu lệnh bên ngoài lớp, hay chỉ cho phép các lớp có quan hệ đặc biệt như là quan hệ lớp con, (và quan hệ bạn bè (friend) trong C++) được phép dùng tới nó (hay thay đổi giá trị của nó). Mỗi thuộc tính của một lớp còn được gọi là thành viên dữ liệu của lớp đó.

Quan hệ giữa lớp và đối tượng

Lớp trong quan niệm thông thường là cách phân loại các thực thể dựa trên những đặc điểm chung của các thực thể đó. Do đó lớp là khái niệm mang tính trừu tượng hóa rất cao. Ví dụ như lớp "người" dùng để chỉ những thực thể sống trên Trái Đất có những thuộc tính: có hai chân, hai bàn tay khéo léo, có tư duy, ngôn ngữ v.v và có phương thức: giao tiếp bằng ngôn ngữ, tư duy, đi, đứng bằng hai chân... Khi đó hai người cụ thể ông A, ông B là các đối tượng thuộc lớp người. Trong ngôn ngữ lập trình, ta cũng hiểu khái niệm lớp tương tự, cho nên ta có quá trình "Thực thể hóa" sau, tạo một đối tượng thuộc một lớp đã được ta định nghĩa (phân loại).

Thực thể (instance)

Thực thể hóa (instantiate) là quá trình khai báo để có một tên (có thể được xem như là một biến) trở thành một đối tượng từ một lớp nào đó.
Một lớp sau khi được tiến hành thực thể hóa để có một đối tượng cụ thể gọi là một thực thể. Hay nói ngược lại một thực thể là một đối tượng riêng lẻ của một lớp đã định trước. Như các biến thông thường, hai thực thể của cùng một lớp có thể có trạng thái nội tại khác nhau (xác định bởi các giá trị hiện có của các biến nội tại) và do đó hoàn toàn độc lập nhau nếu không có yêu cầu gì đặc biệt từ người lập trình. " Thực thể hóa: gần giống như cá nhân hóa. Một lớp khi được " cá nhân hóa" sẽ thành một đối tượng cụ thể.

Riêng tư (private)

Riêng tư là sự thể hiện tính chất đóng mạnh nhất (của một đặc tính hay một lớp). Khi dùng tính chất này gán cho một biến, một phương thức thì biến hay phương thức đó chỉ có thể được sử dụng bên trong của lớp mà chúng được định nghĩa. Mọi nỗ lực dùng trực tiếp đến chúng từ bên ngoài qua các câu lệnh hay từ các lớp con sẽ bị phủ nhận hay bị lỗi.

Bảo tồn (protected)

Tùy theo ngôn ngữ, sẽ có vài điểm nhỏ khác nhau về cách hiểu tính chất này. Nhìn chung đây là tính chất mà khi dùng để áp dụng cho các phương thức, các biến nội tại, hay các lớp thì chỉ có trong nội bộ của lớp đó hay các lớp con của nó (hay trong nội bộ một gói như trong Java) được phép gọi đến hay dùng đến các phương pháp, biến hay lớp đó.
So với tính chất riêng tư thì tính bảo tồn rộng rãi hơn về nghĩa chia sẻ dữ liệu hay chức năng. Nó cho phép một số trường hợp được dùng tới các đặc tính của một lớp (từ một lớp con chẳng hạn).
Lưu ý: Các tính chất công cộng, riêng tư và bảo tồn đôi khi còn được dùng để chỉ thị cho một lớp con cách thức kế thừa một lớp cha như trong C++.

Lịch sử

Khái niệm về các đối tượng và thực thể trong khoa học máy tính được nhiều người biết đến từ hệ thống PDP-1 của MIT. Đây có lẽ là Ví dụ sớm nhất của kiến trúc cơ sở có khả năng thực. Một bằng chứng sớm khác của OOP được tìm thấy qua Sketchpad viết bởi Ivan Sutherland trong năm 1963, tuy nhiên, đây chỉ là một ứng dụng chứ không là một mẫu hình lập trình.
Ngôn ngữ lập trình hướng đối tượng đầu tiên là Simula, ngôn ngữ này được thiết kế để dùng trong các việc mô phỏng, được sáng tạo bởi Ole-Johan Dahl và Kristen Nygaard thuộc Trung tâm Máy tính Na Uy ở Oslo. Các kiến thức trong ngôn ngữ này sau đó đã được dùng trong nhiều ngôn ngữ khác, bắt đầu từ Lisp và Pascal cho đến họ ngôn ngữ Smalltalk.
Lập trình hướng đối tượng đã được phát triển như là phương pháp lập trình chủ đạo từ giữa thập niên 1990 nguyên do đáng kể là việc ảnh hưởng của C++, một ngôn ngữ mở rộng của C. Địa vị thống trị của OOP đã được củng cố vững chắc bởi sự phổ biến của các GUI dành cho ngôn ngữ lập trình hướng đối tượng ngày càng tiện lợi. Một Ví dụ về quan hệ gần gũi của thư viện GUI động và ngôn ngữ OOP là phần mềm Cocoa, nó là khung cơ sở của Mac OS X dược viết bằng Objective C (Objective C là một loại ngôn ngữ hướng đối tượng mở rộng của C với việc thông báo động). Công cụ cho OOP cũng được nâng cao phần "lập trình điều khiển theo sự kiện" (mặc dù khái niệm này không chỉ dành cho OOP).
Tại Zürich, Niklaus Wirth và những cộng sự đã theo dõi các đề tài như là dữ liệu trừu tượng và lập trình mô đun. Modula-2 bao gồm cả hai đặc tính đó. Thiết kế liền tiếp theo là Oberon bao gồm sự tiếp cận riêng biệt với việc định hướng đối tượng, các lớp,... Sự tiếp cận này không như Smalltalk, và cũng khác hẳn C++.
Các chức năng của hướng đối tượng cũng đã đang được thêm vào nhiều ngôn ngữ trong suốt thời gian đó kể cả Ada, BASIC, Lisp, Fortran, Pascal và nhiều nữa. Việc cộng thêm các chức năng đó cho các ngôn ngữ mà được trước đó không chủ định thiết kế cho chúng ngay từ đầu cũng thường dẫn tới nhiều khó khăn trong khả năng tương thích (với mã nguồn viết cho các phiên bản cũ) và khả năng bảo trì mã. Điển hình của trường hợp này là Pascal và Visual Basic. Các ngôn ngữ thuần túy hướng đối tượng, ở phía khác, lại thiếu các đặc tính mà nhiều người lập trình phụ thuộc vào. Để bắc cầu cho khoảng trống này, nhiều nỗ lực đã được xúc tiến để tạo ra các ngôn ngữ đặt cơ sở trên các phương pháp hướng đối tượng nhưng lại cho phép dùng nhiều đặc tính lập trình cấu trúc theo những phương cách "an toàn". Ngôn ngữ Eiffel của Bertrand Meyer đã sớm thành công với các mục tiêu này.
Trong thập niên đã qua, Java được dùng rộng rãi một phần là do sự tương tự với C và C++, nhưng có lẽ do phần khác quan trọng hơn là việc lắp đặt sử dụng máy ảo mà chủ ý là thực thi cùng một mã nguồn cho nhiều nền tảng khác nhau. .NET của Microsoft cũng mở đầu với các chủ ý tương tự và cộng thêm việc hỗ trợ nhiều ngôn ngữ hay các sự biến thể của các ngôn ngữ cũ (như trường hợp C# và Visual Basic).
Gần đây, một số ngôn ngữ xuất hiện với chức năng chính là định hướng đối tượng nhưng lại tương thích được với phương pháp thủ tục như là Python và Ruby. Bên cạnh Java, C# và Visual Basic.NET là hai ngôn ngữ OOP quan trọng hiện tại thiết kế bởi Microsoft.
Giống như lập trình thủ tục đã dẫn tới việc tinh lọc các kỹ thuật như là lập trình cấu trúc, phần mềm hướng đối tượng hiện đại thiết kế các phương pháp bao gồm các sự tinh lọc. Chẳng hạn như là việc ứng dụng các dạng thức thiết kế, thiết kế bởi hợp đồng và các ngôn ngữ mô hình trong đó có UML.