Nhung Cau Hoi Phong Van

8
OOP 1 : Tiến trình trừu tượng của các ngôn ngữ lập trình Mọi ngôn ngữ lập trình (NNLT) đều mang một mức độ trừu tượng nhất định. Mức độ phức tạp của mỗi vấn đề/bài toán (cần giải quyết bằng phương pháp lập trình) thực tế phụ thuộc vào mức độ trừu tượng này. Hợp ngữ (assembly) là một sự trừu tượng từ ngôn ngữ máy (mã máy được sinh ra khi ta biên dịch các đoạn code assembly - vốn gồm các từ khóa "gần giống tiếng Anh"). Những NNLT như Fortran, BASIC hay C là một mức độ trừu tượng cao hơn (có cấu trúc) của hợp ngữ. Những NNLT này là sự cải tiến lớn so với hợp ngữ; tuy nhiên ở mức độ trừu tượng của những NNLT này, lập trình viên (LTV) vẫn phải tư duy về cấu trúc máy tính hơn là cấu trúc vấn đề cần giải quyết. Tức là LTV phải thiết lập sự liên hệ giữa mô hình máy tính và mô hình vấn đề thực tế. Điều này đem đến nhiều thách thức trong công việc coding cũng như bảo trì code. Thay thế cho việc mô hình hóa máy tính là sự mô hình hóa vấn đề cần giải quyết. Những ngôn ngữ như LISP hay APL đem đến cách nhìn nhận vấn đề từ khía cạnh khác (chẳng hạn như "mọi vấn đề cuối cùng cũng chỉ là những danh sách" hay "mọi vấn đề đều có tính giải thuật"). Tương tự như vậy, PROLOG quan niệm mọi vấn đề là "chuỗi những quyết định". Mỗi ngôn ngữ trên được thiết kế riêng (và là phương án tốt) cho mỗi loại bài toán; tuy nhiên, nếu để giải quyết một loại bài toán có đặc tính cơ bản khác hẳn thì tiêu liền. Tiếp cận vấn đề bằng phương pháp lập trình hướng đối tượng (object-oriented programming - OOP) là một bước nhảy vọt trong tư duy lập trình. Lập trình hướng đối tượng là động tác mô hình hóa các thành phần trong miền vấn đề (problem space). Sự mô hình hóa này có tính tổng quát đủ để giải phóng LTV ra khỏi sự ràng buộc về kiểu/loại vấn đề/bài toán. Người ta gọi những thành phần trong miền vấn đề khi được mô hình hóa là những đối tượng (objects). Mỗi đối tượng, tương tự như các đối tượng trong thế giới thực, có những thuộc tính và hành vi riêng của mình. Do phương pháp tư duy OOP rất gần với cách thức tư duy của con người, LTV sẽ được tự do chú trọng vào cấu trúc vấn đề - điều cần giải quyết - hơn là cấu trúc máy. Thực tế, OOP mang đến một mức độ trừu tượng mềm dẻo và mạnh mẽ hơn những cách tiếp cận trước đây. Alan Kay rút ra được 5 tính chất cơ bản của SmallTalk NNLT OO phổ biến đầu tiên, đó là : 1. Mọi thứ đều là đối tượng (everything is an object). Hãy xem như mỗi đối tượng là một biến đặc biệt. Một đối tượng ngoài việc mang dữ liệu (như các biến thường), còn có thể "được yêu cầu, ra lệnh" từ LTV. 2. Một chương trình là một lô một lốc các đối tượng có thể "nói chuyện" với

Transcript of Nhung Cau Hoi Phong Van

Page 1: Nhung Cau Hoi Phong Van

OOP 1 : Tiến trình trừu tượng của các ngôn ngữ lập trình

Mọi ngôn ngữ lập trình (NNLT) đều mang một mức độ trừu tượng nhất định. Mức độ phức tạp của mỗi vấn đề/bài toán (cần giải quyết bằng phương pháp lập trình) thực tế phụ thuộc vào mức độ trừu tượng này. Hợp ngữ (assembly) là một sự trừu tượng từ ngôn ngữ máy (mã máy được sinh ra khi ta biên dịch các đoạn code assembly - vốn gồm các từ khóa "gần giống tiếng Anh"). Những NNLT như Fortran, BASIC hay C là một mức độ trừu tượng cao hơn (có cấu trúc) của hợp ngữ. Những NNLT này là sự cải tiến lớn so với hợp ngữ; tuy nhiên ở mức độ trừu tượng của những NNLT này, lập trình viên (LTV) vẫn phải tư duy về cấu trúc máy tính hơn là cấu trúc vấn đề cần giải quyết. Tức là LTV phải thiết lập sự liên hệ giữa mô hình máy tính và mô hình vấn đề thực tế. Điều này đem đến nhiều thách thức trong công việc coding cũng như bảo trì code. 

Thay thế cho việc mô hình hóa máy tính là sự mô hình hóa vấn đề cần giải quyết. Những ngôn ngữ như LISP hay APL đem đến cách nhìn nhận vấn đề từ khía cạnh khác (chẳng hạn như "mọi vấn đề cuối cùng cũng chỉ là những danh sách" hay "mọi vấn đề đều có tính giải thuật"). Tương tự như vậy, PROLOG quan niệm mọi vấn đề là "chuỗi những quyết định". Mỗi ngôn ngữ trên được thiết kế riêng (và là phương án tốt) cho mỗi loại bài toán; tuy nhiên, nếu để giải quyết một loại bài toán có đặc tính cơ bản khác hẳn thì tiêu liền. 

Tiếp cận vấn đề bằng phương pháp lập trình hướng đối tượng (object-oriented programming - OOP) là một bước nhảy vọt trong tư duy lập trình. Lập trình hướng đối tượng là động tác mô hình hóa các thành phần trong miền vấn đề (problem space). Sự mô hình hóa này có tính tổng quát đủ để giải phóng LTV ra khỏi sự ràng buộc về kiểu/loại vấn đề/bài toán. Người ta gọi những thành phần trong miền vấn đề khi được mô hình hóa là những đối tượng (objects). Mỗi đối tượng, tương tự như các đối tượng trong thế giới thực, có những thuộc tính và hành vi riêng của mình. Do phương pháp tư duy OOP rất gần với cách thức tư duy của con người, LTV sẽ được tự do chú trọng vào cấu trúc vấn đề - điều cần giải quyết - hơn là cấu trúc máy. Thực tế, OOP mang đến một mức độ trừu tượng mềm dẻo và mạnh mẽ hơn những cách tiếp cận trước đây. 

Alan Kay rút ra được 5 tính chất cơ bản của SmallTalk NNLT OO phổ biến đầu tiên, đó là :�  

1. Mọi thứ đều là đối tượng (everything is an object). Hãy xem như mỗi đối tượng là một biến đặc biệt. Một đối tượng ngoài việc mang dữ liệu (như các biến thường), còn có thể "được yêu cầu, ra lệnh" từ LTV.2. Một chương trình là một lô một lốc các đối tượng có thể "nói chuyện" với nhau bằng cách gửi các thông điệp (a program is a bunch of objects telling each other what to do by sending message). Để "ra lệnh" cho một đối tượng, LTV "gửi một thông điệp" đến đối tượng đó. Cụ thể hơn, một thông điệp cũng giống như một câu gọi hàm (hàm của đối tượng).3. Mỗi đối tượng có vùng nhớ riêng được tạo nên từ những đối tượng khác (each object has its own memory made up of other objects). Có thể hiểu là, một đối tượng có thể được cấu thành từ nhiều đối tượng có sẵn khác. Vì vậy, LTV có thể xây dựng một chương trình mà mức độ phức tạp được ẩn giấu sau sự giản dị (dễ dùng) của các đổi tượng.4. Mọi đối tượng có một kiểu nhất định (every object has a type). Mỗi đối tượng là một phiên bản của một lớp/kiểu/loại. Ví dụ như đối tượng con Kiki nhà tôi là một phiên bản của lớp chó, hay con Kiki thuộc lớp chó.5. Mọi đối tượng cùng kiểu đều có thể nhận cùng thông điệp (all object of a particular type can receive the same messages). Ví dụ như mọi con thuộc lớp chó đều biết cách sủa, con Kiki cũng không ngoại lệ.

Page 2: Nhung Cau Hoi Phong Van

Booch đề xuất một cách mô tả súc tích hơn về đối tượng : Một đối tượng có trạng thái, có hành vi và được định danh (an object has state, behaviour and identity )

OOP 2 Service Pack 1 : Review & Relax

[Khẩu hiệu : Relax today is more important than Review] 

Ôn lại một chút, bạn phân biệt được class và object hay không ? Hy vọng bạn còn nhớ class giống như một bản thiết kế mô tả các tính năng và thông số yêu cầu; còn object chính là sự hiện sinh của bản thiết kế ấy. Với class trong tay, người ta có thể sinh ra bao nhiêu object cũng được (lúc đó object sinh ra được gọi là instance* của class). Các object có tương ứng các thuộc tính/tính chất (properties) và phương thức/hành vi (methods). Một cách ngắn gọn, class là trừu tượng (abstract), còn object là cụ thể (concrete). Sau đây là các ví dụ : 

* instance thường được các dịch giả Ngọc Anh Thư Press (FPT-Aptech đại diện Aptech khởi kiện về việc ăn cắp tác quyền quyển OOP with Java - Aptech) dịch là minh dụ. Tớ thấy ngớ ngẩn làm sao ấy nhưng lại cũng không tìm được từ tiếng Việt thích hợp nên xin phép không dịch từ này. 

1. Các nhà thiết kế ôtô đưa ra một bản thiết kế loại xe LOOF mui trần tuyệt đẹp, nhà sản xuất Tlik dựa trên bản thiết kế ấy xuất xưởng hai chiếc Katrina (màu xanh) và Phoenix (màu đỏ). Nếu như bản thiết kế có mô tả rằng loại xe LOOF này ngoài các chức năng bình thường còn có thể chạy Twin Turbo mode (TTM) thì thề có Chúa, chắc chắn cả Katrina lẫn Phoenix đều chạy được TTM. Dễ thấy, bản thiết kế xe là một class (được đặt tên là LOOF), còn hai chiếc Katrina và Phoenix là 2 objects được sinh ra từ class LOOF, tuân theo những tiêu chuẩn được mô tả bởi mẫu LOOF. Tuy nhiên đừng cho rằng 2 object này giống hệt nhau mà lầm, vì giá trị các thuộc tính của ‘họ’ khác nhau (ví dụ : màu xe). 

2. Chúa sau khi thiết kế (design) class Male và khởi tạo (initialize) một object Adam, đã thiết kế ra một class khác hấp dẫn sinh động hơn nhiều. Người gọi lớp này là Female, và khởi tạo ngay một object Eva. Chúng ta chẳng hơi đâu mà xem xét đến ông Adam lẫn class Malecủa ổng, hãy để sức mà quan tâm đến class Female, cụ thể là bản thiết kế rút gọn sau : 

Text Code:Lựa chọn code | Ẩn/Hiện code

Class Female(properties)HeightWeightHairSkinColorMoodVoiceToneVoiceRangeSensType...(methods)ScreamShoutCryMoanSmile...

Page 3: Nhung Cau Hoi Phong Van

(events - cái này sẽ được nói về sau,nôm na là các biến cố)BeUnderSunShineBeCriticizedBeBrokenUp...End ClassChúa tạo ra hàng tỷ tỷ phụ nữ trên trái đất, và mỗi phụ nữ dù ở đâu hay thuộc dân tộc gì cũng đều là... phụ nữ (ý tớ là thuộc class Female). Mấy chị châu Phi có property SkinColor = Black trong khi các cô châu Âu có property SkinColor = White. Ca sĩ Ánh Tuyết có property VoiceTone = VeryHigh nên giọng mới cao như vậy. Giả sử cô Hot_snow nhà ta (cũng thuộc class Female) mà rơi vào 'biến cố' bị kick thì event BeBrokenUp sẽ được raise, từ đó có thể phát sinh ra các methods Moan hay Cry tuỳ giá trị property SensType. Nếu các cô các chị đi nắng thì event BeUnderSunShine sẽ được raise lên, dẫn đến kết quả là màu da giảm độ sáng (SkinColor = SkinColor - 1).

Kết luận : với các objects được sinh ra từ cùng một class thì các tính chất và hành vi tổng thể là như nhau, nhưng được phân biệt bởi các giá trị thuộc tính đặc thù của mỗi object. 

OOP 3 : Hidden Implementation

[Để đổi không khí và Anh ngữ hoá thuật ngữ, tớ thay LTV bằng programmer nhé. Nghe pro hơn và cũng oai hơn nhiều. Một số thuật ngữ khác xin được phép giữ nguyên, để hỗ trợ cho các bạn trong "công cuộc kháng chiến trường kỳ" với English IT books.] 

Trong thế giới OOP, người ta phân programmers làm 2 nhánh : class creators và client programmers. Vậy class creators là gì ? Đó là mấy cha chuyên lo thiết kế các classes. Còn client programmers chính là mấy người xài những classes do class creators thiết kế. Mục tiêu của client programmers là thu thập những classes hữu dụng để phát triển nhanh ứng dụng cho đề án của họ. Mục tiêu của class creators là thiết kế những classes cung cấp những chức năng cần thiết (trong khi giữ kín những thành phần khác). Những thành phần "ẩn" này là những thành phần tinh tế bên trong mỗi object, sẽ dễ bị sai lạc do những bất cẩn của client programmer nếu như được hiển thị. Vì thế, làm ẩn đi những thành phần thực thi sẽ giảm thiểu program bugs. 

Nếu mọi thành phần của một class được để lộ "trần trùi trụi", client programmer sẽ có thể nghịch tới bến với class đó -> vô phương để áp đặt các quy tắc (bảo vệ) lên class -> cần thiết phải có các nguyên tắc điều khiển truy xuất (access control) cho class. 

Nguyên tắc access control là "cách ly" client programmer khỏi các thành phần "tế nhị" của class. Nè, đừng nghĩ access control sẽ hạn chế sự linh hoạt của client programmer. Chính nó mang lại những nhiều tiện ích cho client programmer bởi nó làm giản đơn việc điều khiển class thông qua một giao diện (lớp bọc) giữa class và client programmer. Những thành phần nào private của class, client programmer sẽ không thể truy xuất đến được. Thử nghĩ về cái TV nhà bạn xem, giao diện của TV là các nút bấm volume +/-, channel +/- v.v... bạn chỉ (cần) thấy mấy cái nút đó là đủ sử dụng TV rồi, đâu cần phải biết các bóng đèn, mạch điện bên trong (hidden/private code/implementation - những thành phần "tế nhị"). Nếu TV nhà bạn không có vỏ (không có access control) thì mấy đứa nhỏ táy máy chọc tay/chân/cây vô nghịch mấy cái mạch thì không những dễ tiêu TV mà cả tụi nhóc cũng thế. -> bảo đảm những nguyên tắc (an toàn) điều khiển class. 

Page 4: Nhung Cau Hoi Phong Van

* C++/Java/C# cung cấp các từ khóa cho access control (gọi là access modifiers) như public, protected, private. Ngoài ra còn có friend, internal, protected internal. 

Với access control, nhà thiết kế thư viện có thể thay đổi mã thực thi (thường là sửa lỗi hay cải tiến) trong class mà không làm ảnh hưởng đến công việc của client programmer (vì giao diện class không đổi). Ví dụ nhé : ngoài chiếc Honda Custom 50cc maxspeed 60 kmph, hãng HONDA còn thiết kế loại Honda Custom 70cc maxspeed 90 kmph với vẻ ngoài và cách thức điều khiển xe như nhau. Bạn với các kỹ năng điều khiển xe không thay đổi, có thể chuyển từ HC50 sang HC70 dễ dàng. Điều này giống như sự thay đổi hidden implementation (độ phân khối) mà vẫn không ảnh hưởng client programmer (người sử dụng xe) do giao diện điều khiển là không đổi. -> class creators dễ cải tiến chương trình mà không (mấy) ảnh hưởng đến client programmers.

OOP 4 : Tái sử dụng mã - Code Reusability

Mỗi class sau khi được thiết kế và kiểm tra (test) cẩn thận được xem như một đơn vị code hữu dụng. Client programmer sử dụng những class này cho các ứng dụng của họ (xài chùa hay mua lại). Như vậy một class được viết ra có thể được dùng lại rất rất nhiều lần ở các ứng dụng khác. Tính "tái dụng mã" (code reusability) là một trong những thế mạnh lớn nhất mà những NNLT hướng đối tượng cung cấp. 

Phương pháp tái dụng mã đơn giản nhất là khởi tạo trực tiếp một object từ class có sẵn. Điều này giống như bạn đi xin (nếu được, nhưng chắc phải mua) bản thiết kế nhà (class có sẵn) của người khác, đem về thiết kế một cái nhà (object) cho riêng mình. 

Cách khác là thiết kế một class cho riêng bạn, mà trong class này sử dụng object của class có sẵn (gọi là tạo object thành viên - member object). Liên hệ ra đời sống : giống như mấy nhà máy sản xuất xe máy ở VN, nguyên cả cái xe máy là của mình thiết kế, nhưng một vài bộ phận khó thì chịu, đến khi sản xuất xe (tạo object) thì mấy bộ phần này phải nhập (object member) -> xe máy VN. Cách này được gọi là composition hay tổng quát hơn là aggregation. Quan hệ giữa class mới và class có sẵn là quan hệ "có"/"has-a" (xe máy VN "có" động cơ Campuchia). 

Composition mang lại sự linh hoạt tuyệt vời. Thường thì các member objects trong class mới sẽ được đặt là private -> vô hình đối với client programmer. Nếu các member objects được thay đổi (thường là được nâng cấp, xảy ra khi class của các member objects được nâng cấp) thì class mới của bạn cũng được hưởng lợi. 

Lập trình hướng đối tượng được đặc trưng bởi một cái... bánh 3 miếng. Không lạ, không lạ đối với những OO programmers, đó là Polymorphism (tính đa hình), Inheritance (tính thừa kế) và Encapsulation (tính đóng gói) -> 3 miếng hợp thành một cái bánh (PIE). Chương này bàn về code reusability nên chúng ta sẽ xem xét miếng Inheritance trước, hai miếng còn lại để dành ăn sau. 

Thừa kế (inheritance) là khái niệm muôn đời quan trọng của lập trình hướng đối tượng. Những nhà lập trình OO tương lai nên luôn tâm niệm rằng, tận dụng được inheritance là các bạn đã có sức mạnh to lớn của OOP. Đương nhiên, cũng như thực tế, được thừa kế,

Page 5: Nhung Cau Hoi Phong Van

tức không làm mà có xài chơi thì ai mà hổng khoái ? Nhưng, hãy nhớ rằng inheritance ngoài cung cấp khả năng tái dụng mã còn cho phép class creators thiết lập hệ thống cấp bậc cho các class. 

Giả sử Chúa thiết kế được class Horse như sau : 

Text Code:Lựa chọn code | Ẩn/Hiện code

class Horse(properties)...(methods)GallopWhinny...end class

một ngày nọ, Chúa bỗng muốn có một loài ngựa biết bay cho thế giới thêm màu sắc. Nếu như thiết kế lại từ đầu một loài ngựa mới có các tính chất và hành vi như ngựa thường, thêm vào khả năng bay thì quả là tốn nhiều công sức. Thế nên, phương pháp thừa kế được Người sử dụng như sau :

Text Code:Lựa chọn code | Ẩn/Hiện code

class Pegasus inherits from Horse(methods)Flyend class

Với phương pháp này, loài Pegasus này sẽ thừa hưởng tất cả những gì loài Horse có, ngoài ra loài này còn có thêm khả năng riêng là "bay". Class Pegasus được gọi là sub/child/derived/inherited class, còn class Horse được gọi là super/base/parent class. Quan hệ giữa base class và sub class là quan hệ "là"/"is-a". Ta có thể nói một con Thiên Mã (Pegasus) là một con Ngựa (Horse), đơn giản vì nó rút cuộc cũng chỉ là một con ngựa, cho dù nó biết bay.

Các NNLT hướng đối tượng chạy qua hệ nền trung gian (và có cơ chế lượm rác - Garbage Collector) như Java hay C# (không có OOPL nào là thực sự OO pure) chỉ hỗ trợ thừa kế đơn (tuy nhiên hỗ trợ đa giao diện - multi-interface - sẽ bàn sau). Tức là mỗi sub class chỉ thừa kế trực tiếp từ tối đa một base class mà thôi. Điều này được quy định để hỗ trợ cho cơ chế lượm rác hoạt động, thoạt xem có vẻ như hạn chế công tác lập trình nhưng thực chất là góp phần cho code được sáng sủa. Còn, hic, C++ thì bất chấp, một sub class có thể được thừa kế từ nhiều base class. Một ví dụ đa thừa kế : code:

Text Code:Lựa chọn code | Ẩn/Hiện code

class Horse (xem phía trên)

Page 6: Nhung Cau Hoi Phong Van

class Bird(properties)...(methods)FlySing...end class

class Pegasus inherits from Horse and Birdend class

với những gì thừa hưởng từ hai loài Horse và Bird, loài Pegasus có khả năng phi nước đại (gallop), hí (whinny), bay (fly) và thậm chí... hót (sing).

C Code:

struct NhanVien2:{   char Ten[255];   int MSNV;   char DiaChi[255];   int DienThoai[7];};

ban viet nhu the thi van ton bo nho qua.nen sua thanhC++ Code:

struct NhanVien2:{   char Ten[255];   char DiaChi[255];   int MSNV;   int DienThoai[7];};