MÔN LẬP TRÌNH HƯỚNG ĐỐI TƯỢNGChương 1 ÔN LẠI CÁC TÍNH CHẤT CỦA LẬP TRÌNH CẤU TRÚC... Cấu trúc 1 chương trình hướng cấu trúc Thành phần “giải thuật” bao gồm code ₫ược viết trong các modu
Trang 1
BÀI GIẢNG: MÔN LẬP TRÌNH HƯỚNG
ĐỐI TƯỢNG
Trang 2MÔN LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG
Đối tượng : SV ₫ại học chính quy ngành CNTT
Tài liệu tham khảo :
Tập slide bài giảng & thực hành của môn học này.
The C++ Programming Language (special 3rd edition),
Bjarne Stroustrup, 2000.
3 CD MSDN trong Microsoft Visual Studio.
Online-Help của môi trường JBuilder
Trang 3MÔN LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG
Nội dung chính gồm 10 chương :
1 Ôn lại các tính chất của lập trình cấu trúc.
2 Các khái niệm chính của lập trình OOP.
3 Cơ chế dịch mã OOP sang mã máy.
4 Tổng quát về mức ₫ộ hỗ trợ OOP của VC++ & Java.
5 Đặc tả class & các tính chất cơ bản của ₫ối tượng trong VC++.
6 Đặc tả class & các tính chất cơ bản của ₫ối tượng trong Java.
7 Chi tiết về gọi hàm, gởi thông ₫iệp & ₫a xạ của VC++.
8 Chi tiết về gọi hàm, gởi thông ₫iệp & ₫a xạ của Java.
9 Chi tiết về thường trú, serialization, COM, Generalization & Template
của VC++.
10 Chi tiết về thường trú, serialization, Generalization của Java.
Trang 4MÔN LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG
Chương 1
ÔN LẠI CÁC TÍNH CHẤT CỦA LẬP TRÌNH CẤU TRÚC
Trang 5Phương pháp phân tích từ-trên-xuống
Mỗi sự vật trong môi trường xung quanh ta ₫ều ₫ược cấu thành từ nhiều phần tử nhỏ hơn, mỗi phần tử nhỏ lại ₫ược cấu thành từ nhiều phần tử nhỏ hơn nữa Thí
dụ, con người gồm ₫ầu, mình, tứ chi Tứ chi gồm 2 tay và 2 chân
Mỗi công việc cần giải quyết bằng máy tính cũng ₫ược cấu thành từ nhiều công việc nhỏ hơn, mỗi công việc nhỏ hơn lại ₫ược cấu thành từ nhiều công việc nhỏ hơn nữa
Phương pháp phân tích từ-trên-xuống (top-down analysis) là phương pháp thường
sử dụng ₫ể phân tích công việc, nội dung của phương pháp này là cố gắng xác
₫ịnh xem công việc cần giải quyết ₫ược cấu thành từ những công việc nhỏ nào, mỗi công việc nhỏ ₫ược cấu thành từ các công việc nhỏ hơn nào, cứ như vậy cho
₫ến khi những công việc xác ₫ịnh ₫ược là những công việc thật ₫ơn giản, có thể thực hiện dễ dàng.
Thí dụ việc học lấy bằng kỹ sư CNTT khoa CNTT ĐHBK TP.HCM có thể bao gồm
9 công việc nhỏ hơn là học từng học kỳ từ 1 tới 9, học học kỳ i là học n môn học của học kỳ ₫ó, học 1 môn học là học m chương của môn ₫ó,
Hình vẽ của slide kế cho thấy trực quan của phương pháp phân tích top-down.
Trang 6Phương pháp phân tích từ-trên-xuống (tt)
Công việc cần giải quyết (A)
chia thành nhiều công
việc nhỏ hơn, ₫ơn giản ₫ể
giải quyết hơn.
Các công việc ₫ủ nhỏ
₫ể ₫ược miêu tả bằng
1 lệnh hay 1 lời gọi
hàm/thủ tục ₫ã có.
Trang 7Tầm vực truy xuất biến
Tầm vực của một biến là tập các lệnh ₫ược phép truy xuất biến ₫ó.
C và C++ cho phép 3 cấp ₫ộ tầm vực sau :
o cục bộ trong function : bất kỳ lệnh nào trong function ₫ều có thể truy xuất
₫ược biến cục bộ trong function ₫ó.
void Command1_Click() {
char strGreeting[256]; // Khai báo cục bộ
}
o cục bộ trong module : bất kỳ lệnh nào trong module ₫ều có thể truy xuất
₫ược biến cục bộ trong module ₫ó.
static char strAddr[256]; // biến cục bộ trong module
char strName[256]; // biến toàn cục
o toàn cục : bất kỳ lệnh nào trong chương trình cũng có thể truy xuất ₫ược
biến toàn cục.
Trong một ngữ cảnh (cùng 1 function, cùng 1 module, hay cấp toàn cục), không thể dùng hai biến cùng tên (C phân biệt chữ HOA và chữ thường).
Trang 8Cấu trúc 1 chương trình hướng cấu trúc
Chương trình = cấu trúc dữ liệu + giải thuật
Trang 9Cấu trúc 1 chương trình hướng cấu trúc
Thành phần “giải thuật” bao gồm code ₫ược viết trong các module Trong từng module, code ₫ược gom nhóm thành những hàm chức năng, mỗi hàm ₫ược nhận dạng và truy xuất thông qua tên hàm.
Thành phần “dữ liệu” bao gồm các biến dữ liệu ₫ược ₫ịnh nghĩa trong các module Trong từng module, về mặt tầm vực truy xuất, các biến có thể ₫ược
₫ịnh nghĩa 1 trong 2 cấp tầm vực :
Public : bất kỳ lệnh nào của chương trình ₫ều có thể truy xuất ₫ược.
Private : chỉ có các lệnh trong module hiện hành mới có thể truy xuất.
Ngoài ra trong từng hàm chức năng, người ta có thể ₫ịnh nghĩa các biến cục
bộ, các biến này chỉ ₫ược truy xuất cục bộ bởi các lệnh trong hàm tương ứng Ngoại lệ, trong 1 số ngôn ngữ như C, người ta cho phép ₫ịnh nghĩa biến trong lệnh thực thi (block — compose), biến này chỉ ₫ược truy xuất cục bộ bởi các lệnh trong thân của lệnh block tương ứng.
Ö ₫iểm yếu nhất trong ngôn ngữ hướng cấu trúc là cho phép ₫ịnh nghĩa biến toàn cục, nếu biến này bị lỗi, ta rất khó xác ₫ịnh nguyên nhân gây lỗi Việc mang 1 hàm hay 1 module của ứng dụng này sang ứng dụng khác cũng sẽ khó khăn vì
Trang 10Cấu trúc 1 chương trình hướng cấu trúc
Xét Turbo Pascal, 1 ứng dụng gồm 1 module chương trình và
nhiều module dịch vụ ₫ược gọi là Unit Để sử dụng các thành phần trong 1 module nào ₫ó, ta phải dùng lệnh Use
1 file gồm nhiều hàm chức năng Điểm nhập ứng dụng là hàm
main() Module C cũng có thể là file thư viện liên kết tĩnh (*.lib) hay
₫ộng (*.dll) Để sử dụng các thành phần trong 1 module nào ₫ó, ta phải dùng lệnh #include
Trang 11Mối quan hệ client/server giữa các module
//₫ặc tả interface của module B : server extern int B_intA;
typedef struct { } B_Type1;
#define B_MAXLEN 1024 int B_func1(char c, char* d);
//₫ặc tả interface của module A : client
#include B.h
extern int A_intA;
typedef struct { } A_Type1;
#define A_PI 3.14159
int A_func1(int a, double b);
#include B.h //hiện thực của module B int B_intA;
static int B_intB;
int B_func1(int a, double b) {
B_func2(a);
} static void B_func2(int a) { }
#include A.h
//hiện thực của module A
int A_intA;
static int A_intB;
int A_func1(int a, double b) {
Trang 12Hai module sử dụng tài nguyên của nhau
//₫ặc tả interface của module B
#define _BH
#ifndef _AH
#include A.h
#endif extern int B_intA;
typedef struct { } B_Type1;
#define B_PI 3.14159 int B_func1(char c, char* d);
//₫ặc tả interface của module A
#define _AH
#ifndef _BH
#include B.h
#endif
extern int A_intA;
typedef struct { } A_Type1;
#define A_PI 3.14159
int A_func1(int a, double b);
#include B.h //hiện thực của module B int B_intA;
static int A_intB;
int B_func1(int a, double b) {
B_func2(a);
} static void B_func2(int a) { }
#include A.h
//hiện thực của module A
int A_intA;
static int A_intB;
int A_func1(int a, double b) {
Trang 13MÔN LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG
Chương 2
CÁC KHÁI NIỆM CHÍNH CỦA LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG
Trang 14Nội dung
2.1 Cấu trúc của 1 ứng dụng hướng ₫ối tượng
2.2 Đối tượng, thuộc tính, tác vụ.
2.3 Abstract type và class.
Trang 15Cấu trúc chương trình OOP
Chương trình = tập các ₫ối tượng tương tác nhau
Trang 16Cấu trúc chương trình OOP
Cấu trúc chương trình hướng ₫ối tượng rất thuần nhất, chỉ chứa
1 loại thành phần : ₫ối tượng
Các ₫ối tượng có tính ₫ộc lập rất cao ⇒ quản lý, kiểm soát
chương trình rất dễ (cho dù chương trình có thể rất lớn) ⇒ dễ
nâng cấp, bảo trì
Không thể tạo ra dữ liệu toàn cục của chương trình ⇒ ₫iểm yếu nhất của chương trình cấu trúc không tồn tại nữa
Trang 17Đối tượng (Object)
Đối tượng là nguyên tử cấu thành ứng dụng.
Đối tượng bao gồm 2 loại thành phần :
thuộc tính (dữ liệu) : mỗi thuộc tính mang 1 giá trị nhất ₫ịnh tại
Trang 18Kiểu trừu tượng (Abstract type)
Abstract type (type) ₫ịnh nghĩa interface sử dụng ₫ối tượng Ta
dùng tên nhận dạng ₫ể ₫ặt tên cho kiểu và ₫ể nhận dạng nó
Interface là tập hợp các 'entry' mà bên ngoài có thể giao tiếp với
₫ối tượng
Ta dùng signature ₫ể ₫ịnh nghĩa mỗi 'entry' Signature gồm :
tên tác vụ (operation, function)
danh sách tham số hình thức, mỗi tham số ₫ược ₫ặc tả bởi 3 thuộc tính : tên, type và chiều di chuyển (IN, OUT, INOUT)
₫ặc tả chức năng của tác vụ (thường ở dạng chú thích)
Ta dùng tên của abstract type (chứ không phải class) ₫ể ₫ặc tả
kiểu cho biến, thuộc tính, tham số hình thức
User không cần quan tâm ₫ến class (hiện thực cụ thể) của ₫ối
tượng
Trang 19Kiểu trừu tượng trong Java
Java h ỗ trợ kiểu trừu tượng th ông qua lệnh interface , l ệnh này ₫ịnh nghĩa
abstract type của nhiều ₫ối tượng của ứng dụng (có thể thuộc nhiều class khác
nhau
public interface Sleeper {
public void wakeUp();
public long ONE_SECOND = 1000; // in milliseconds
public long ONE_MINUTE = 60000; // in milliseconds
}
public class DigitalClock extends Applet implements Sleeper {…}
public class AnalogClock extends Applet implements Sleeper {…}
Trang 20Class (Implementation)
~ Ta dùng tên nhận dạng ₫ể ₫ặt tên cho class và ₫ể nhận dạng nó
Class ₫ịnh nghĩa chi tiết hiện thực ₫ối tượng :
₫ịnh nghĩa các thuộc tính dữ liệu , mỗi thuộc tính ₫ược ₫ặc tả bởi các thông tin về nó như tên nhận dạng, kiểu dữ liệu, tầm vực truy xuất, Kiểu của thuộc tính có thể là type cổ ₫iển (số nguyên, thực,
ký tự, chuỗi ký tự, ) hay 'abstract type', trong trường hợp sau thuộc tính sẽ là tham khảo ₫ến ₫ối tượng khác Trạng thái của ₫ối tượng
là tập giá trị tại thời ₫iểm tương ứng của tất cả thuộc tính của ₫ối tượng Trong thời gian tồn tại và hoạt ₫ộng, trạng tái của ₫ối tượng
sẽ thay ₫ổi.
'coding' các tác vụ (miêu tả giải thuật chi tiết về hoạt ₫ộng của tác vụ) và các 'internal function'.
~ Định nghĩa các tác vụ tạo (create) và xóa (delete) ₫ối tượng
~ Định nghĩa các tác vụ 'constructor' và 'destructor'.
~ User không cần quan tâm ₫ến class của ₫ối tượng.
Trang 21Ví dụ về ₫ịnh nghĩa class trongVC++
class CMiniChatClientDlg : public CDialog {
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg void OnConnect();
Trang 22Tính bao ₫óng (encapsulation)
Bao ₫óng : che dấu mọi chi tiết hiện thực của ₫ối tượng, không
cho bên ngoài thấy và truy xuất ⇒ tạo ₫ộ ₫ộc lập cao giữa các
₫ối tượng (hay tính kết dính - cohesion giữa các ₫ối tượng rất
che dấu chi tiết hiện thực các tác vụ
che dấu các internal function và sự hiện thực của chúng
Java, VC++ cung cấp các từ khóa private, protected, public ₫ể
xác ₫ịnh tầm vực truy xuất từng thành phần của class
Trang 23Tính thừa kế (inheritance)
Tính thừa kế cho phép giảm nhẹ công sức ₫ịnh nghĩa type/class : ta
có thể ₫ịnh nghĩa các type/class không phải từ ₫ầu mà bằng cách kế thừa type/class có sẵn, ta chỉ ₫ịnh nghĩa thêm các chi tiết mới mà thôi (thường khá ít)
Đa thừa kế hay ₫ơn thừa kế.
Thừa kế tạo ra mối quan hệ supertype/subtype và
superclass/subclass.
Có thể override các method của class cha, kết quả override chỉ tác dụng trên ₫ối tượng của class con.
Đối tượng của class con có thể ₫óng vai trò của ₫ối tượng class
cha nhưng ngược lại thường không ₫ược
VC++ cho phép hạn chế tầm vực truy xuất các thành phần của class
cha :
class C : protected A, private B {…}
Trang 26int xPos, yPos;
double xScale, yScale;
Trang 27Thông ₫iệp (Message)
Thông ₫iệp là 1 phép gọi tác vụ ₫ến 1 ₫ối tượng từ 1 tham
khảo
tham khảo ₫ến ₫ối tượng ₫ích
Tên tác vụ muốn gọi
danh sách tham số thực cần truyền theo (hay nhận về từ)
tác vụ
ví dụ : aCircle.SetRadius (3); aCircle.Draw (pWnd);
Thông ₫iệp là phương tiện giao tiếp (hay tương tác) duy nhất
giữa các ₫ối tượng
Trang 28Tính ₫a xạ (Polymorphism)
Cùng 1 lệnh gởi thông ₫iệp ₫ến ₫ối tượng thông qua cùng 1 tham
khảo nhưng ở vị trí/thời ₫iểm khác nhau có thể kích hoạt việc thực thi tác vụ khác nhau của các ₫ối tượng khác nhau
T1 p1; // C1 và C2 là 2 class Java hiện thực T1
p1 = New C1; // tạo ₫ối tượng C1, gán tham khảo vào biến p1
p1.meth1( ); // gởi thông ₫iệp nhờ tác vụ meth1 thực thi
p1 = New C2; // tạo ₫ối tượng C2, gán tham khảo vào biến p1
p1.meth1( ); // gởi thông ₫iệp nhờ tác vụ meth1 thực thi
Lệnh gởi thông ₫iệp p1.meth1( ); ở 2 vị trí khác nhau kích hoạt
2 tác vụ khác nhau của 2 class khác nhau
Trang 29Kiểm tra kiểu (type check)
Chặt và dùng mối quan hệ 'conformity' (tương thích tổng quát)
Type A tương thích với type B ⇔ A chứa mọi tác vụ của B và ứng với từng tác vụ của type B :
Tồn tại 1 tác vụ cùng tên trong A
danh sách tham số của 2 tác vụ tương ứng phải bằng nhau
về số lượng tham số
kiểu ₫ối số OUT hay giá trị return của tác vụ trong A phải
tương thích với kiểu của ₫ối số tương ứng trong B
kiểu ₫ối số IN của tác vụ trong B phải tương thích với kiểu
của ₫ối số tương ứng trong A
kiểu ₫ối số INOUT phải trùng với kiểu của ₫ối số tương ứng trong B
Ö quan hệ so trùng hay quan hệ con/cha (sub/super) là trường hợp
₫ặc biệt của quan hệ tương thích tổng quát
Trang 30Tính tổng quát hóa (Generalization)
Có 2 ngữ nghĩa khác nhau của tính tổng quát hóa :
class tổng quát hóa cho phép sản sinh tự ₫ộng các class bình thường, các class bình thường tự nó chỉ có thể tạo ra ₫ối
tượng Thường dùng ngữ nghĩa này trong giai ₫oạn lập trình
ngược với tính thừa kế : supertype/superclass là type/class
tổng quát hóa của các con của nó Thường dùng ngữ nghĩa này trong giai ₫oạn phân tích/thiết kế phần mềm
Trang 31Tính thường trú (persistence)
Thời gian sống của 1 ₫ối tượng ₫ộc lập với thời gian sống của
phần tử (ứng dụng, ₫ối tượng khác) tạo ra nó
Đối tượng phải tồn tại khi còn ít nhất 1 tham khảo ₫ến nó
thường trú không phải là vĩnh hằng Mức ₫ộ có thể là 1
session của máy ảo (JVM) hay lâu dài (thông qua ₫ĩa cứng, CDROM)
Trang 32Tổng kết
Mô hình hướng ₫ối tượng quan niệm thế giới (hay chương trình) bao
gồm các ₫ối tượng ₫ộc lập sống chung và tương tác lẫn nhau.
Các ₫ặc ₫iểm chính của mô hình hướng ₫ối tượng :
Bao ₫óng : mỗi ₫ối tượng bao gồm 1 số dữ liệu và tác vụ Các tác
vụ thiết lập nên hành vi của ₫ối tượng Các ₫ối tượng cùng loại
Trang 33MÔN LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG
Chương 3
CƠ CHẾ DỊCH MÃ HƯỚNG ĐỐI TƯỢNG
SANG MÃ MÁY
Trang 34Tổng quát về vấn ₫ề dịch OOP
Chương trình là tập các ₫ối tượng sống ₫ộc lập và tương tác lẫn nhau khi cần thiết
Các ₫ối tượng thuộc 1 số loại nhất ₫ịnh (n)
Mỗi loại ₫ối tượng ₫ược miêu tả bởi 1 type & 1 class
Mã nguồn chương trình là tập n ₫ịnh nghĩa type & class
Dịch chương trình OOP là qui trình lặp dịch n type & n class
Ta sẽ miêu tả qui trình dịch 1 type và 1 class trong chương này
Trang 35Dịch 1 abstract type
Abstract type chỉ chứa thông tin trừu tượng (interface), không
miêu tả sự hiện thực → Kết quả việc dịch 1 type chỉ dừng lại ở
việc xây dựng cây ngữ nghĩa của type tương ứng ₫ể phục vụ việc kiểm tra kiểu của chương trình dịch, chứ không tạo code mã máy
Chỉ cần 3 bước : duyệt từ vựng, phân tích cú pháp và phân tích ngữ nghĩa
vựng & phân tích cú pháp
Trang 36Dịch 1 class
Dịch class là công việc chính của chương trình dịch hướng ₫ối
tượng
Gồm 2 công việc chính : dịch thuộc tính dữ liệu và dịch các
method (hay các internal function)
Cần ₫ầy ₫ủ các bước : duyệt từ vựng, phân tích cú pháp, phân
tích ngữ nghĩa và tạo mã
vựng & phân tích cú pháp
Trang 37int proc4(int i);
void proc5 (double d);
} C1;
Trang 38Dịch thuộc tính dữ liệu (tt)
mỗi class → 1 record dữ liệu cổ ₫iển
tên class → tên record
copy các field dữ liệu của cấu trúc sinh ra từ việc dịch class cha
Chuyển từng thuộc tính của class thành từng field của record,
“tuyệt ₫ối hóa” tên của thuộc tính ₫ể tránh nhặp nhằng
thêm các field dữ liệu ₫iều khiển phục vụ cho run-time : thí dụ
bảng ₫ịa chỉ các tác vụ của ₫ối tượng (pvftbl)
Trang 39Dịch thuộc tính dữ liệu (tt)
cấu trúc record ₫ược dịch ra mã máy thành 1 vùng nhớ liên tục có
₫ộ dài bằng ₫ội dài của record
- khai báo biến C1 o1; C1_o1 db dup (sizeof(C1))
truy xuất 1 thuộc tính dữ liệu trở thành việc truy xuất ô nhớ dùng cách ₫ịnh ₫ịa chỉ chỉ số :
mov [bx+8], 5
Trang 40void proc2(); //override
int proc4(int i, double k);
void proc5 (double d);