Một đối tượng là gì?
Java được biết đến là một ngôn ngữ hướng đối tượng (object-oriented), bạn có thể sử dụng ngôn ngữ này để lập trình hướng đối tượng (còn được gọi là OOP). Điều này rất khác so với lập trình thủ tục, và có thể hơi lạ lùng đối với hầu hết các lập trình viên chưa tìm hiểu về hướng đối tượng. Bước đầu tiên bạn phải hiểu đối tượng là gì, vì đó là khái niệm cơ sở của lập trình hướng đối tượng.
Một đối tượng là một tập hợp mã lệnh tự thân trọn vẹn (self-contained), tự hiểu chính nó và có thể nói cho các đối tượng khác về nó nếu đưa ra các yêu cầu mà nó hiểu được. Một đối tượng có các thành phần dữ liệu (các biến thành phần) và các method (Phương thức), chính là những gì để nó biết cách trả lời một yêu cầu mà nó hiểu (dù chúng không được diễn đạt bằng lời như các câu hỏi). Tập các method mà một đối tượng được gọi là giao diện của đối tượng. Một vài method được publish (nghĩa là các đối tượng khác có thể gọi đến chúng). Tập các method publish này được gọi là giao diện publish của đối tượng.
Khi một đối tượng gọi method của một đối tượng khác, thì được hiểu là gửi một thông điệp (sending a message) đến đối tượng khác. Cụm từ này là thuật ngữ của Hướng đối tượng nhưng hầu hết trong giới Java mọi người hay nói: "gọi method này" hơn là "gửi thông điệp này".
Ví dụ minh họa đối tượng
Giả sử chúng ta có đối tượng Person, mỗi Person có các thuộc tính tên, tuổi, chủng tộc và giới tính. Mỗi Person đều biết nói và biết đi. Một Person có thể hỏi tuổi của một Person khác, hoặc yêu cầu một Person khác đi hay đứng lại. Diễn đạt theo thuật ngữ lập trình, bạn có thể tạo một đối tượng Person và khai báo một số biến (như tên và tuổi). Nếu bạn tạo một đối tượng Person thứ hai, đối tượng này có thể hỏi tuổi của đối tượng thứ nhất hoặc yêu cầu đối tượng thứ nhất đi. Nó có thể thực hiện những điều ấy bằng cách gọi đến các method của đối tượng Person đầu tiên. Khi chúng ta bắt đầu viết mã lệnh bằng ngôn ngữ Java, bạn sẽ hiểu ngôn ngữ này triển khai thực hiện khái niệm đối tượng ra sao.
Nói chung, khái niệm đối tượng là như nhau trong ngôn ngữ Java và các ngôn ngữ hướng đối tượng khác, mặc dù việc triển khai thực hiện là khác nhau giữa các ngôn ngữ. Lập trình viên hướng đối tượng, bất chấp họ lập trình bằng ngôn ngữ nào, có xu hướng phát biểu khác so với những lập trình viên thủ tục. Các lập trình viên thủ tục thường nói về các hàm và các mô đun. Lập trình viên hướng đối tượng lại nói về các đối tượng và họ thường nói về các đối tượng này bằng cách sử dụng các đại từ nhân xưng. Chẳng hề bất thường khi bạn nghe một lập trình viên hướng đối tượng nói với đồng nghiệp, "đối tượng Supervisor nói với đối tượng Employee, cho tôi ID của cậu" vì anh ta cần những thứ này để gán nhiệm vụ cho Employee.
Lập trình viên hướng thủ tục có thể nghĩ cách nói chuyện này thật lạ lùng, nhưng nó lại hoàn toàn bình thường đối với lập trình viên hướng đối tượng. Trong thế giới lập trình của họ, mọi thứ đều là đối tượng (cũng có một vài ngoại lệ đáng chú ý trong ngôn ngữ Java) và các chương trình là chỉ là sự tương tác (hay nói chuyện) giữa các đối tượng với nhau.
Các tính chất hướng đối tượng cơ bản
Khái niệm đối tượng là trọng yếu đối với lập trình hướng đối tượng, và dĩ nhiên, ý tưởng các đối tượng giao tiếp với nhau bằng các thông điệp cũng vậy. Nhưng có 3 tính chất cơ bản mà bạn cần hiểu.
Bạn có thể nhớ 3 tính chất hướng đối tượng cơ bản bằng cụm viết tắt PIE:
- Đa hình (Polymorphism)
- Thừa kế (Inheritance)
- Bao gói (Encapsulation)
Đó là những từ trừu tượng nhưng những khái niệm này thực sự không quá khó hiểu. Trong các phần tiếp theo, chúng ta sẽ bàn về từng khái niệm này ở mức độ chi tiết hơn, theo thứ tự ngược lại.
Tính chất Bao gói (Encapsulation)
Hãy nhớ rằng một đối tượng phải là tự thân trọn vẹn, chứa đựng các thành phần dữ liệu và hành động mà nó có thể thực hiện trên các thành phần dữ liệu ấy. Đây là việc triển khai thực hiện nguyên lý gọi là ẩn giấu thông tin. Ý tưởng của nó là một đối tượng tự nó hiểu được nó. Nếu một đối tượng khác muốn điều gì từ đối tượng này thì nó phải hỏi. Theo thuật ngữ lập trình hướng đối tượng, phải gửi một thông điệp đến một đối tượng khác để hỏi thông tin. Theo thuật ngữ Java, phải gọi một method của đối tượng khác để nó trả lại kết quả là tuổi.
Sự bao gói đảm bảo rằng mỗi đối tượng là khác nhau và chương trình là một cuộc chuyện trò giữa các đối tượng. Ngôn ngữ Java cho phép các lập trình viên vi phạm nguyên lý này nhưng hầu như luôn là một ý tưởng tồi nếu làm như thế.
Tính chất Thừa kế (Inheritance)
Khi bạn được sinh ra, nói ở khía cạnh sinh học, bạn là tổ hợp DNA của cha mẹ mình. Bạn không hoàn toàn giống ai trong số họ, mà bạn giống cả hai người. Lập trình hướng đối tượng cũng có tính chất tương tự đối với các đối tượng tự nhiên. Quay lại với đối tượng Person ở ví dụ trên, ta nhớ lại rằng mỗi người có một chủng tộc. Không phải tất cả các Person đều cùng chủng tộc, nhưng dù sao thì họ cũng có điểm tương tự như nhau chứ? Chắc chắn vậy! Họ chẳng phải ngựa, tinh tinh hay cá voi mà là người. Mọi con người đều có những điểm chung nhất định và điều này giúp phân biệt con người với các loài động vật khác. Nhưng giữa mọi người cũng có khác biệt với nhau. Một đứa trẻ có giống hệt một người trưởng thành không? Không. Đi lại và nói là khác nhau rồi. Nhưng một đứa trẻ thì vẫn chắc chắn là một con người.
Theo ngôn ngữ hướng đối tượng, Person và Baby là các lớp sự vật hiện tượng thuộc cùng một hệ thống phân bậc, và Baby thừa kế các đặc tính và hành vi từ lớp cha của nó. Chúng ta có thể nói rằng một Baby cụ thể là một kiểu Person hay Baby thừa kế từ Person. Nhưng không có chiều ngược lại – một Person không nhất thiết phải là một Baby. Mỗi đối tượng Baby là một cá thể của lớp Baby và khi chúng ta tạo một đối tượng Baby, chúng ta cá thể hóa lớp này. Hãy coi lớp như là khuôn mẫu chung cho các cá thể của lớp đó. Nói chung, đối tượng có thể làm những gì tùy thuộc vào kiểu của đối tượng đó là gì – hoặc nói theo cách khác, đối tượng đó là cá thể của lớp nào. Cả Baby và Adult đều thuộc kiểu Person, nhưng đối tượng Adult có thể có một việc làm còn đối tượng Baby thì không.
Theo thuật ngữ Java: Person là một lớp bậc trên (superclass) của Baby và Adult, Baby và Adult là lớp con của Person. Một khái niệm có liên quan đến kế thừa là ý tưởng về trừu tượng hóa (abstract), Person có mức trừu tượng hóa cao hơn Baby hay Adult. Cả hai đều là kiểu Person nhưng có những khác biệt nho nhỏ. Tất cả các đối tượng Person đều có những điểm chung (như tên và tuổi). Bạn có thể cá thể hóa một Person? Thực sự là không! Bạn hoặc có một Baby hoặc có một Adult. Trong Java, Person được gọi là lớp trừu tượng, bạn không thể trực tiếp có một cá thể của lớp Person. Bạn sẽ có Baby hoặc Adult, cả hai đều là kiểu Person, nhưng là Person đã được thực tế hóa.
Các lớp trừu tượng nằm ngoài phạm vi của bài viết này, tôi sẽ không nói thêm về chúng nữa. Bây giờ, ta hãy suy nghĩ xem với một Baby, nói có nghĩa là gì. Chúng ta sẽ xét đến các hệ quả trong phần thảo luận tiếp theo.
Tính chất Đa hình (Polymorphism)
Baby có nói như Adult không? Dĩ nhiên là không rồi. Một Baby có thể ê a, nhưng không nhất thiết nói ra những lời hiểu được như Adult. Do đó, nếu tôi cá thể hóa một đối tượng Baby (hay là cá thể hóa một Baby cũng có cùng ý nghhĩa – từ đối tượng được ngầm hiểu ở đây) và cho nó nói, thì nó chỉ có nghĩa là đối tượng Baby nói những tiếng ê a. Ta hy vọng rằng Adult nói thì mạch lạc hơn.
Trong hệ thống phân bậc con người, chúng ta có Person nằm ở đỉnh với Baby và Adult nằm phía dưới nó, là các lớp con. Tất cả mọi người đều có thể nói, Baby và Adult cũng vậy, nhưng sẽ nói khác nhau. Baby chỉ ê a và phát những âm thanh đơn giản, còn Adult nói thành lời rõ ràng. Đó chính là mô tả về đa hình các đối tượng làm việc theo cách riêng của chúng.
Ngôn ngữ Java là (và không là) Hướng đối tượng ở chỗ nào?
Như chúng ta sẽ thấy, ngôn ngữ Java cho phép bạn tạo các đối tượng là ưu tiên trước (first-class), nhưng không phải bất cứ cái gì trong ngôn ngữ này đều là đối tượng. Một số ngôn ngữ Hướng đối tượng như Smalltalk lại hoàn toàn khác, Smalltalk hoàn toàn là Hướng đối tượng, có nghĩa là mọi thứ trong ngôn ngữ này đều là đối tượng. Java là ngôn ngữ lai tạp giữa đối tượng và phi đối tượng. Nó cho phép một đối tượng biết rõ các đối tượng khác, nếu với tư cách là một lập trình viên bạn cho phép điều đó xảy ra. Điều này vi phạm nguyên lý bao gói.
Tuy nhiên, ngôn ngữ Java cũng cung cấp cho tất cả các lập trình viên Hướng đối tượng những công cụ cần thiết để tuân theo mọi quy tắc Hướng đối tượng và viết mã lệnh Hướng đối tượng rất chuẩn. Nhưng làm được như vậy cần phải tự có kỷ luật (Như kiểu cộng đồng C Việt cho phép gửi bài viết chung chung ở box nhập môn, nhưng ở các box khác thì không ). Ngôn ngữ không ép bạn làm việc đúng đắn như máy được nhưng sẽ có những nguyên tắc nhất định.
Trong khi những người thuần túy chủ nghĩa hướng đối tượng tranh luận xem liệu Java là hướng đối tượng hay không, thực sự đây không phải là một lý lẽ mang lại ích lợi. Nền tảng Java sẽ giữ vững vị trí của nó giống như C và C++. Hãy học cách lập trình hướng đối tượng tốt nhất có thể với mã lệnh Java và cứ để những lý lẽ thuần túy chủ nghĩa cho những người khác. Ngôn ngữ Java giúp bạn viết chương trình rõ ràng, khá ngắn gọn, dễ bảo trì.
Java được biết đến là một ngôn ngữ hướng đối tượng (object-oriented), bạn có thể sử dụng ngôn ngữ này để lập trình hướng đối tượng (còn được gọi là OOP). Điều này rất khác so với lập trình thủ tục, và có thể hơi lạ lùng đối với hầu hết các lập trình viên chưa tìm hiểu về hướng đối tượng. Bước đầu tiên bạn phải hiểu đối tượng là gì, vì đó là khái niệm cơ sở của lập trình hướng đối tượng.
Một đối tượng là một tập hợp mã lệnh tự thân trọn vẹn (self-contained), tự hiểu chính nó và có thể nói cho các đối tượng khác về nó nếu đưa ra các yêu cầu mà nó hiểu được. Một đối tượng có các thành phần dữ liệu (các biến thành phần) và các method (Phương thức), chính là những gì để nó biết cách trả lời một yêu cầu mà nó hiểu (dù chúng không được diễn đạt bằng lời như các câu hỏi). Tập các method mà một đối tượng được gọi là giao diện của đối tượng. Một vài method được publish (nghĩa là các đối tượng khác có thể gọi đến chúng). Tập các method publish này được gọi là giao diện publish của đối tượng.
Khi một đối tượng gọi method của một đối tượng khác, thì được hiểu là gửi một thông điệp (sending a message) đến đối tượng khác. Cụm từ này là thuật ngữ của Hướng đối tượng nhưng hầu hết trong giới Java mọi người hay nói: "gọi method này" hơn là "gửi thông điệp này".
Ví dụ minh họa đối tượng
Giả sử chúng ta có đối tượng Person, mỗi Person có các thuộc tính tên, tuổi, chủng tộc và giới tính. Mỗi Person đều biết nói và biết đi. Một Person có thể hỏi tuổi của một Person khác, hoặc yêu cầu một Person khác đi hay đứng lại. Diễn đạt theo thuật ngữ lập trình, bạn có thể tạo một đối tượng Person và khai báo một số biến (như tên và tuổi). Nếu bạn tạo một đối tượng Person thứ hai, đối tượng này có thể hỏi tuổi của đối tượng thứ nhất hoặc yêu cầu đối tượng thứ nhất đi. Nó có thể thực hiện những điều ấy bằng cách gọi đến các method của đối tượng Person đầu tiên. Khi chúng ta bắt đầu viết mã lệnh bằng ngôn ngữ Java, bạn sẽ hiểu ngôn ngữ này triển khai thực hiện khái niệm đối tượng ra sao.
Nói chung, khái niệm đối tượng là như nhau trong ngôn ngữ Java và các ngôn ngữ hướng đối tượng khác, mặc dù việc triển khai thực hiện là khác nhau giữa các ngôn ngữ. Lập trình viên hướng đối tượng, bất chấp họ lập trình bằng ngôn ngữ nào, có xu hướng phát biểu khác so với những lập trình viên thủ tục. Các lập trình viên thủ tục thường nói về các hàm và các mô đun. Lập trình viên hướng đối tượng lại nói về các đối tượng và họ thường nói về các đối tượng này bằng cách sử dụng các đại từ nhân xưng. Chẳng hề bất thường khi bạn nghe một lập trình viên hướng đối tượng nói với đồng nghiệp, "đối tượng Supervisor nói với đối tượng Employee, cho tôi ID của cậu" vì anh ta cần những thứ này để gán nhiệm vụ cho Employee.
Lập trình viên hướng thủ tục có thể nghĩ cách nói chuyện này thật lạ lùng, nhưng nó lại hoàn toàn bình thường đối với lập trình viên hướng đối tượng. Trong thế giới lập trình của họ, mọi thứ đều là đối tượng (cũng có một vài ngoại lệ đáng chú ý trong ngôn ngữ Java) và các chương trình là chỉ là sự tương tác (hay nói chuyện) giữa các đối tượng với nhau.
Các tính chất hướng đối tượng cơ bản
Khái niệm đối tượng là trọng yếu đối với lập trình hướng đối tượng, và dĩ nhiên, ý tưởng các đối tượng giao tiếp với nhau bằng các thông điệp cũng vậy. Nhưng có 3 tính chất cơ bản mà bạn cần hiểu.
Bạn có thể nhớ 3 tính chất hướng đối tượng cơ bản bằng cụm viết tắt PIE:
- Đa hình (Polymorphism)
- Thừa kế (Inheritance)
- Bao gói (Encapsulation)
Đó là những từ trừu tượng nhưng những khái niệm này thực sự không quá khó hiểu. Trong các phần tiếp theo, chúng ta sẽ bàn về từng khái niệm này ở mức độ chi tiết hơn, theo thứ tự ngược lại.
Tính chất Bao gói (Encapsulation)
Hãy nhớ rằng một đối tượng phải là tự thân trọn vẹn, chứa đựng các thành phần dữ liệu và hành động mà nó có thể thực hiện trên các thành phần dữ liệu ấy. Đây là việc triển khai thực hiện nguyên lý gọi là ẩn giấu thông tin. Ý tưởng của nó là một đối tượng tự nó hiểu được nó. Nếu một đối tượng khác muốn điều gì từ đối tượng này thì nó phải hỏi. Theo thuật ngữ lập trình hướng đối tượng, phải gửi một thông điệp đến một đối tượng khác để hỏi thông tin. Theo thuật ngữ Java, phải gọi một method của đối tượng khác để nó trả lại kết quả là tuổi.
Sự bao gói đảm bảo rằng mỗi đối tượng là khác nhau và chương trình là một cuộc chuyện trò giữa các đối tượng. Ngôn ngữ Java cho phép các lập trình viên vi phạm nguyên lý này nhưng hầu như luôn là một ý tưởng tồi nếu làm như thế.
Tính chất Thừa kế (Inheritance)
Khi bạn được sinh ra, nói ở khía cạnh sinh học, bạn là tổ hợp DNA của cha mẹ mình. Bạn không hoàn toàn giống ai trong số họ, mà bạn giống cả hai người. Lập trình hướng đối tượng cũng có tính chất tương tự đối với các đối tượng tự nhiên. Quay lại với đối tượng Person ở ví dụ trên, ta nhớ lại rằng mỗi người có một chủng tộc. Không phải tất cả các Person đều cùng chủng tộc, nhưng dù sao thì họ cũng có điểm tương tự như nhau chứ? Chắc chắn vậy! Họ chẳng phải ngựa, tinh tinh hay cá voi mà là người. Mọi con người đều có những điểm chung nhất định và điều này giúp phân biệt con người với các loài động vật khác. Nhưng giữa mọi người cũng có khác biệt với nhau. Một đứa trẻ có giống hệt một người trưởng thành không? Không. Đi lại và nói là khác nhau rồi. Nhưng một đứa trẻ thì vẫn chắc chắn là một con người.
Theo ngôn ngữ hướng đối tượng, Person và Baby là các lớp sự vật hiện tượng thuộc cùng một hệ thống phân bậc, và Baby thừa kế các đặc tính và hành vi từ lớp cha của nó. Chúng ta có thể nói rằng một Baby cụ thể là một kiểu Person hay Baby thừa kế từ Person. Nhưng không có chiều ngược lại – một Person không nhất thiết phải là một Baby. Mỗi đối tượng Baby là một cá thể của lớp Baby và khi chúng ta tạo một đối tượng Baby, chúng ta cá thể hóa lớp này. Hãy coi lớp như là khuôn mẫu chung cho các cá thể của lớp đó. Nói chung, đối tượng có thể làm những gì tùy thuộc vào kiểu của đối tượng đó là gì – hoặc nói theo cách khác, đối tượng đó là cá thể của lớp nào. Cả Baby và Adult đều thuộc kiểu Person, nhưng đối tượng Adult có thể có một việc làm còn đối tượng Baby thì không.
Theo thuật ngữ Java: Person là một lớp bậc trên (superclass) của Baby và Adult, Baby và Adult là lớp con của Person. Một khái niệm có liên quan đến kế thừa là ý tưởng về trừu tượng hóa (abstract), Person có mức trừu tượng hóa cao hơn Baby hay Adult. Cả hai đều là kiểu Person nhưng có những khác biệt nho nhỏ. Tất cả các đối tượng Person đều có những điểm chung (như tên và tuổi). Bạn có thể cá thể hóa một Person? Thực sự là không! Bạn hoặc có một Baby hoặc có một Adult. Trong Java, Person được gọi là lớp trừu tượng, bạn không thể trực tiếp có một cá thể của lớp Person. Bạn sẽ có Baby hoặc Adult, cả hai đều là kiểu Person, nhưng là Person đã được thực tế hóa.
Các lớp trừu tượng nằm ngoài phạm vi của bài viết này, tôi sẽ không nói thêm về chúng nữa. Bây giờ, ta hãy suy nghĩ xem với một Baby, nói có nghĩa là gì. Chúng ta sẽ xét đến các hệ quả trong phần thảo luận tiếp theo.
Tính chất Đa hình (Polymorphism)
Baby có nói như Adult không? Dĩ nhiên là không rồi. Một Baby có thể ê a, nhưng không nhất thiết nói ra những lời hiểu được như Adult. Do đó, nếu tôi cá thể hóa một đối tượng Baby (hay là cá thể hóa một Baby cũng có cùng ý nghhĩa – từ đối tượng được ngầm hiểu ở đây) và cho nó nói, thì nó chỉ có nghĩa là đối tượng Baby nói những tiếng ê a. Ta hy vọng rằng Adult nói thì mạch lạc hơn.
Trong hệ thống phân bậc con người, chúng ta có Person nằm ở đỉnh với Baby và Adult nằm phía dưới nó, là các lớp con. Tất cả mọi người đều có thể nói, Baby và Adult cũng vậy, nhưng sẽ nói khác nhau. Baby chỉ ê a và phát những âm thanh đơn giản, còn Adult nói thành lời rõ ràng. Đó chính là mô tả về đa hình các đối tượng làm việc theo cách riêng của chúng.
Ngôn ngữ Java là (và không là) Hướng đối tượng ở chỗ nào?
Như chúng ta sẽ thấy, ngôn ngữ Java cho phép bạn tạo các đối tượng là ưu tiên trước (first-class), nhưng không phải bất cứ cái gì trong ngôn ngữ này đều là đối tượng. Một số ngôn ngữ Hướng đối tượng như Smalltalk lại hoàn toàn khác, Smalltalk hoàn toàn là Hướng đối tượng, có nghĩa là mọi thứ trong ngôn ngữ này đều là đối tượng. Java là ngôn ngữ lai tạp giữa đối tượng và phi đối tượng. Nó cho phép một đối tượng biết rõ các đối tượng khác, nếu với tư cách là một lập trình viên bạn cho phép điều đó xảy ra. Điều này vi phạm nguyên lý bao gói.
Tuy nhiên, ngôn ngữ Java cũng cung cấp cho tất cả các lập trình viên Hướng đối tượng những công cụ cần thiết để tuân theo mọi quy tắc Hướng đối tượng và viết mã lệnh Hướng đối tượng rất chuẩn. Nhưng làm được như vậy cần phải tự có kỷ luật (Như kiểu cộng đồng C Việt cho phép gửi bài viết chung chung ở box nhập môn, nhưng ở các box khác thì không ). Ngôn ngữ không ép bạn làm việc đúng đắn như máy được nhưng sẽ có những nguyên tắc nhất định.
Trong khi những người thuần túy chủ nghĩa hướng đối tượng tranh luận xem liệu Java là hướng đối tượng hay không, thực sự đây không phải là một lý lẽ mang lại ích lợi. Nền tảng Java sẽ giữ vững vị trí của nó giống như C và C++. Hãy học cách lập trình hướng đối tượng tốt nhất có thể với mã lệnh Java và cứ để những lý lẽ thuần túy chủ nghĩa cho những người khác. Ngôn ngữ Java giúp bạn viết chương trình rõ ràng, khá ngắn gọn, dễ bảo trì.
إرسال تعليق