Tóm tắt OOP

You might also like

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 27

Tóm tắt OOP

Bài 1: Tổng quan


- Đối tượng thế giới thực: 1 đối tượng thật, có trạng thái và hành động
- Đối tượng phần mềm: đối tượng trong code, có thuộc tính và phương thức
- Lớp (class): một mẫu cho các đối tượng cùng loại
- Các nguyên tắc cơ bản của OOP
o Trừu tượng hóa (abstraction): giữ lại chỉ những đặc điểm cần thiết cho yêu cầu bài
toán
o Đóng gói (encapsulation): che giấu, ẩn đi các chi tiết bên trong
o Thừa kế (inheritance): tạo các lớp con kế thừa thuộc tính và phương thức của lớp
cha
o Đa hình (polymorphism): các phương thức cùng tên, nhưng hoạt động khác nhau
- Nền tảng Java (Java platform): Java program -> Java API -> Java Virtual Machine (JVM)
-> host platform
- Mã nguồn được biên dịch (compile) thành byte code rồi được JVM thông dịch (interpret)
thành mã máy -> không phụ thuộc vào nền tảng, miễn là cài được JVM

Bài 2: Cú pháp Java


- Định danh: tên biến, tên hàm, tên class… Chỉ bao gồm chữ cái, số, ‘$’ hoặc ‘_’, không
được bắt đầu bằng số hay trùng với từ khóa
o Package: tất cả là chữ thường (scraping)
o Class: viết hoa chữ cái đầu trong mỗi từ ghép lại (SingleThreadScraper)
o Phương thức, thuộc tính: như class nhưng chữ đầu là chữ thường
(scrapeSinglePage)
o Hằng: tất cả viết hoa (PROXY_FILE)
- Các kiểu dữ liệu
o Nguyên thủy (primitive)
 int
 float
 char
 bool
 Một kiểu dữ liệu hẹp hơn được ngầm định chuyển sang kiểu dữ liệu rộng
hơn, nếu muốn chuyển ngược lại thì phải báo rõ ràng

o Tham chiếu (reference)


 Là các class, mặc định của Java (Integer, String, Float) hoặc người dùng tự
định nghĩa.
- Toán tử
o Số học: +, -, *, /, %
o Toán tử bit: &, |, ^, ~, <<, >>
o Quan hệ: ==, >=, <=, !=, >, <
o Logic: &&, ||, !
o Thứ tự ưu tiên:

o
- Cấu trúc điều khiển:
o If – else
o Switch – case
o While – do while
o For
o Break – continue
o Phạm vi biến: một biến tồn tại trong scope mà nó được khai báo. 1 scope bắt đầu
bằng { và kết thúc bằng }. Khi các scope lồng nhau mà tên biến trùng nhau thì ưu
tiên dùng biến của scope con
- Mảng: là kiểu tham chiếu (phải dùng toán tử new để khởi tạo)
Bài 3: Lớp, đối tượng và trừu tượng hóa
- Trừu tượng hóa: là một cách nhìn hoặc cách biểu diễn một thực thể chỉ bao gồm các
thuộc tính liên quan trong một ngữ cảnh nào đó.
- Lớp: tập hợp các thể hiện của các thực thể thành các nhóm có chung các thuộc tính
- Đối tượng: là một thể hiện (instance) của lớp

1. Lớp
o Gồm có: tên, thuộc tính và phương thức

o
o Các lớp có quan hệ logic với nhau được cho vào cùng 1 package
o Chỉ định truy cập:

2. Thuộc tính
o Nói chung là các biến ấy mà

3. Phương thức
o Nói chung là các hàm
o Chữ ký phương thức: gồm tên và danh sách KIỂU của tham số
o VD: int a(int b, int c, double d, String e) có chữ ký là a(int, int, double, String)
o Thành viên hằng: từ khóa final khi khai báo biến hoặc hàm – chỉ được gán giá trị
cho biến 1 lần duy nhất. Nếu gán đến lần thứ 2 là lỗi

4. Phương thức khởi tạo


o Là phương thức trùng tên class, chỉ có thể public, private hoặc để trống
o 1 class luôn có ít nhất 1 phương thức khởi tạo. Nếu người dùng k tự viết thì Java
cũng viết hộ (1 phương thức rỗng)
 Như vậy, khi dùng toán tử new, bản chất là ta gọi đến phương thức khởi
tạo của class, tạo ra một đối tượng mới. Tên đối tượng lúc này chỉ là tham
chiếu đến đối tượng thực sự.
 Ví dụ dưới đây in ra 500, vì a1 và a2 trỏ tới cùng 1 đối tượng

5. Các toán tử trong lớp


- Dấu ‘.’ để truy cập các thuộc tính và phương thức của đối tượng và của lớp (như trên,
a1.a là thuộc tính a của đối tượng hehe (1 đối tượng thuộc lớp hehe) mà a1 trỏ tới
- Dùng this trong 1 lớp để trỏ tới chính lớp đó
- Dùng super trong 1 lớp để trỏ tới lớp cha của lớp đó
- Trong ví dụ trên, khi dùng toán tử new, 1 đối tượng thuộc lớp hehehe được tạo ra bằng
phương thức khởi tạo thứ 2 trong hehehe. Trong phương thức này có lời gọi super(a), gọi
đến phương thức khởi tạo của lớp cha của nó, là lớp hehe. Phương thức khởi tạo có 1
tham số kiểu int ứng với phương thức khởi tạo thứ 2 của lớp hehe. Như vậy, giá trị a được
khởi tạo bằng phương thức khởi tạo của hehe, và được gán bằng 1. Sau đó, a (trong lớp
hehehe) được cộng thêm 1. Cuối cùng thì khi in ra, a = 2

4. Các kỹ thuật xây dựng lớp và sử dụng đối tượng


4.1 Nạp chồng phương thức
2 phương thức có tên giống nhau nhưng chữ ký khác nhau sẽ được hiểu khác nhau. Khi gọi, tùy
vào các tham số truyền vào, Java sẽ gọi đến phương thức có chữ ký tương ứng -> nếu k thấy,
hoặc thấy nhiều phương thức thỏa mãn thì sẽ báo lỗi. Như ví dụ ở trên cũng sử dụng nạp chồng
phương thức khởi tạo
4.2 Thành viên static

- Thêm khai báo static trước khi khai báo thành viên lớp để tạo ra 1 thuộc tính hoặc
phương thức THUỘC VỀ LỚP
- Nếu k khai báo static, các thành viên sẽ THUỘC VỀ ĐỐI TƯỢNG, tức là tác động vào
1 thành viên ở 1 đối tượng sẽ chỉ tác động vào mỗi đối tượng đó, còn tác động vào thành
viên thuộc về lớp sẽ tác động tới mọi đối tượng thuộc lớp đó.
- Như vậy, khi khai báo 1 thành viên static, nếu có nhắc đến các thành viên khác, thì các
thành viên khác này cũng phải là static, nếu k sẽ báo lỗi.

-
- VD: lớp Chó có các thuộc tính giống, màu lông, cân nặng, chiều cao, static tổng số con
chó. Các đối tượng thuộc lớp Chó là Chó Nhà Minh, Chó Nhà Thái, Chó Nhà Con
Khánh. Mỗi con chó sẽ có các thuộc tính khác nhau. Nhưng tổng số con chó thì không
thuộc về con chó nào cả, mà thuộc về lớp Chó. Tổng số con chó cũng không thể khai báo
bằng các thuộc tính non-static, tức là không thể có các nào tính tổng số con chó dựa vào
giống, màu lông, cân nặng, chiều cao của 1 con chó được.
- Khi truy cập 1 thuộc tính static, sử dụng tên lớp (vì nó thuộc về lớp chứ không thuộc về
đối tượng). Sử dụng tên đối tượng cũng được nhưng nó sẽ warning (không lỗi)
-
4.3 Thành viên hằng
- Thành viên hằng: thêm khai báo final trước khi khai báo thành viên lớp để tạo ra 1
phương thức hay thuộc tính hằng, tức là không thay đổi được giá trị.
4.4 So sánh đối tượng
- Như đã nói, cái tên chỉ trỏ đến đối tượng, chứ không phải đối tượng thật sự
- Như vậy, khi dùng so sánh == hoặc !=, Java sẽ kiểm tra xem 2 biến đó có CÙNG TRỎ
ĐẾN 1 ĐỐI TƯỢNG hay không. Tức là kể cả các thuộc tính giống hệt nhau, nhưng là 2
đối tượng khác nhau, thì == cũng sẽ là false

- Vậy thì phải tự viết phương thức để kiểm tra tính giống nhau của 2 đối tượng
- Mọi class trong Java (kể cả do người dùng tự định nghĩa) đều là con của class
Object. Trong class Object có phương thức equals -> ghi đè phương thức equals để
dùng

-
4.5 Truyền tham số
- Khi gọi một phương thức, ta truyền các tham số dưới dạng giá trị, tức là:
- Với các kiểu dữ liệu nguyên thủy (primitive), ta truyền được 1 bản copy của nó
- Với các kiểu dữ liệu k nguyên thủy (các đối tượng), ta truyền được 1 bản copy của tham
chiếu đến đối tượng gốc.
- Nghĩa là truyền 1 bản copy của tham chiếu, chứ không phải bản copy của đối tượng. Khi
này đối tượng sẽ có 2 tham chiếu trỏ vào nó

- Trong ví dụ này, he (trong hàm set) là một bản copy của a1, nên he.a++ thì cũng tương
đương với a1.a++ (do he và a1 cùng trỏ tới 1 đối tượng). Nhưng khi gán he = null, thì a1
k bị ảnh hưởng, do he chỉ là 1 bản copy.
4.6 Các lớp bao
- Mỗi kiểu dữ liệu nguyên thủy đều có 1 lớp bao
-

4.7 String
- String lắm vấn đề vkl
- Đầu tiên là dùng toán tử + để ghép các xâu
- Tiếp theo là các phương thức hay hay
-
- So sánh 2 xâu thì dùng a.equals(b) hoặc a.equalsIgnoreCase(b), ý nghĩa thì như tên
- String literal & String Object:
o String literal là kiểu khai báo String a = “Hello”
o String object là kiểu khai báo String a = new String(“Hello”)
o String literal thì dùng 1 cái common pool, những string nào giống nhau trong pool
sẽ được trỏ tới cùng 1 chỗ. Ví dụ có 1 tỷ biến String = “Hello”, thì trong common
pool sẽ chỉ tồn tại 1 xâu “Hello”, và có 1 tỷ cái biến trỏ tới vị trí đấy. Nên là tiết
kiệm bộ nhớ
o String object thì không có common pool, tức là sẽ đẻ ra 1 tỷ cái “Hello” lưu trong
bộ nhớ
- Cuối cùng là String k thay đổi giá trị được. Khi cố thay đổi giá trị, nó sẽ TẠO RA 1
STRING MỚI, BỎ STRING CŨ ĐI, VÀ CHO BIẾN ĐÓ THAM CHIẾU ĐẾN STRING
MỚI.
- -> Rất là mất thời gian.
- VD: String a = “Hello”; // Java tạo ra xâu “Hello” trong common pool, rồi cho a trỏ đến
đấy.
- a = “Hello World”; // Xóa “Hello” trong common pool, tạo “Hello World” trong pool, rồi
cho a trỏ đến đấy
4.8 StringBuffer
- Dùng khi muốn tạo String, và có nhiều thay đổi
-
-

-
5. Kết tập và kế thừa
5.1 Kết tập (Aggregation)
- Tạo ra lớp mới sử dụng các đối tượng của lớp có sẵn. VD như lớp Hình Vuông sử dụng 4
đối tượng Điểm và 4 đối tượng Cạnh
- Lớp mới gọi là lớp toàn thể (Aggregate/Whole)
- Lớp cũ được gọi là lớp thành phần (Part)
- Trong biểu diễn UML, dùng mũi tên có đầu hình thoi rỗng, trỏ vào lớp toàn thể

-
- Khi khởi tạo lớp toàn thể, các lớp thành phần được khởi tạo trước

5.2 Kế thừa (Inheritance)


- Tạo ra một lớp mới dựa vào một lớp có sẵn. VD lớp Chó Sói là 1 lớp con của lớp Chó, kế
thừa các thuộc tính và phương thức của Chó, đồng thời có thêm các thuộc tính và phương
thức mới
- Lớp cha (parent, superclass) còn được gọi là lớp cơ sở (base class)
- Lớp con (child, subclass) còn được gọi là lớp dẫn xuất (derived class)
- Trong biểu diễn UML, dùng mũi tên có đầu tam giác rỗng trỏ vào lớp cha

-
- Có dẫn xuất trực tiếp và dẫn xuất gián tiếp
- Như đã nói, mọi class trong Java đều là dẫn xuất của lớp Object
- Các lớp có cùng cha gọi là anh chị em (siblings)
- Chỉ định truy cập các thành viên lớp:
-
- Cú pháp: class lớp_con extends lớp_cha
- Khi khởi tạo lớp con, lớp cha sẽ được khởi tạo trước và câu lệnh khởi tạo lớp cha phải
được gọi đầu tiên (lệnh super() ). Nếu lớp cha có phương thức khởi tạo mặc định (không
có tham số) thì Java tự thêm, còn nếu mọi phương thức khởi tạo đều có tham số thì mình
phải tự thêm

-
- đây là tự thêm, vì có phương thức khởi tạo mặc định k có tham số

-
- Khi k có phương thức khởi tạo mặc định mà lớp con cũng k gọi khởi tạo thì sẽ báo lỗi
-
- Lớp con gọi phương thức khởi tạo của lớp cha bằng super(int) -> hết lỗi
- Giống như là Con Người, khi khởi tạo thì phải có cân nặng chiều cao. Lớp Học Sinh là
một dẫn xuất của Con Người, thì lúc khởi tạo 1 Học Sinh cũng phải có cân nặng chiều
cao, nếu không sẽ lỗi

6. Một số kỹ thuật trong kế thừa


6.1 Định nghĩa lại (redefine/override)
- Nếu method trong lớp con trùng tên khác chữ ký method trong lớp cha thì chỉ là
overloading
- Nếu trùng chữ ký thì gọi là Redefine/Override
- Khi được gọi đến từ lớp con, sẽ ưu tiên gọi method trong lớp con

-
- Nếu muốn gọi method/attr trong lớp cha (từ trong lớp con) thì dùng super. Nếu muốn gọi
method/attr trong chính lớp này thì dùng this
-
- Lưu ý khi ghi đè: không được ghi đè final và static. Chỉ định truy cập k được chặt hơn
trong lớp cha (cha là protected thì con chỉ có thể protected hoặc public)

6.2 Lớp trừu tượng (abstract class)


- Khai báo: abstract class tên_lớp {…}
- Bên trong CÓ THỂ chứa các PHƯƠNG THỨC TRỪU TƯỢNG (cũng có abstract trước
kiểu phương thức luôn)
- Các phương thức trừu tượng chỉ có thể được khai báo trong lớp trừu tượng
- Các phương thức trừu tượng sẽ được triển khai cụ thể trong các lớp con -> k được để
static hay final.
- Abstract class không được dùng để tạo đối tượng mà chỉ để các class khác extends nó
- Lớp con nếu k phải lớp trừu tượng thì buộc phải triển khai các phương thức trừu tượng
(Dog chưa triển khai makeSound() nên lỗi)

-
- Triển khai xong thì hết lỗi:
-
- Hoặc chuyển Dog thành abstract thì cũng hết lỗi

-
- Nói chung là lớp nào không phải abstract mà kế thừa 1 lớp abstract sẽ phải triển khai hết
đống abstract method của lớp cha
- Ngoài các method abstract ra, lớp abstract cũng có thể có các method bình thường (đã
được triển khai). Tất nhiên là lớp con của nó k cần ghi đè method này

-
- Đấy, chỉ cần triển khai cái makeSound thôi là hết lỗi
6.3 Giao diện (interface)
- Nói chung là bố của abstract class: gồm toàn abstract method (nhưng k dùng từ khóa
abstract). Các thuộc tính cũng là final hoặc static hết.

-
- Cú pháp: interface tên_giao_diện {…}
- Các class khác (bao gồm cả abstract class) sẽ implements các interface. Trong đó phải
triển khai TOÀN BỘ abstract method (nếu là abstract class thì chỉ cần 1 phần)

-
- Trong project cũng có 1 ví dụ của cái này, ở class SingleThreadScraper
-

- Ở đây, Runnable có 1 abstract method là run(), nên trong class này cần triển khai
-

7. Đa hình (polymorphism)
7.1 Upcasting và Downcasting
- Upcasting là việc nhìn nhận lớp con như một lớp cha, tự chuyển đổi kiểu luôn

-
- Downcasting: nhìn nhận lớp cha như 1 lớp con, k tự chuyển kiểu (phải tự ép kiểu)
-
-

-
- Java sử dụng liên kết động (dynamic binding): lời gọi phương thức được quyết định
khi thực hiện (tức là có nhiều cái trùng chữ ký thì chọn cái nào ý – bao giờ chạy thì
nó mới bắt đầu chọn)

7.2 Đa hình (Polymorphism)


- Đa hình trong phương thức (overloading và overriding)
- Đa hình trong cách nhìn nhận đối tượng (nhìn ví dụ bên trên, khai báo hehe a = new
hehehe() vẫn được, bình thường, nó vẫn là một đối tượng hehehe, nhờ tính chất upcasting
– coi con (hehehe) như cha (hehe), nên khai báo cha mà trỏ tới con thì k cần ép kiểu mà
cứ gán bth)
- Toán tử instanceof: do upcast downcast lắm quá nên đ biết nó là kiểu gì -> instanceof

-
- Cả a và b đều là hehe và hehehe -> lớp con và lớp cha được nhìn nhận tương đương nhau

7.3 Lập trình tổng quát


- Ví dụ cần tạo 1 lớp Stack, nhưng những thứ cho vào stack có thể là nhiều thứ khác nhau -
> lợi dụng upcasting và downcasting

-
- Cách thứ 2 là dùng template
- Cú pháp: class tên_class<T> {…}
- T được hiểu là 1 kiểu bất kỳ
- Cũng có thể dùng trong khi truyền tham số vào hàm bằng cách dùng <?>
- Ví dụ

-
-

8. Ngoại lệ và xử lý ngoại lệ
- Ngoại lệ (exception) là cái xảy ra khi thực thi chương trình mà gặp lỗi, VD như nhập 2 số
a b và tính a/b, nhưng người dùng nhập b = 0, hoặc truy cập đến phần tử nằm ngoài
mảng…
- Khi xảy ra ngoại lệ, Java tạo ra một đối tượng ngoại lệ, chứa thông tin chi tiết (lỗi gì, ở
đâu, thằng nào tạo ra…)
- Đối tượng này được ném ra. Khi xuất hiện, cần phải bắt lấy hoặc ném đi tiếp, còn nếu k
xử lý thì ăn cứt luôn
-

- Như trên, các thông tin về ngoại lệ bao gồm: luồng xảy ra ngoại lệ, phân lớp, phân loại,
đến từ hàm nào, file nào, dòng nào trong file

-
- Đây là quá trình “bắt” ngoại lệ, thông qua catch. Ở trên, ta thấy ngoại lệ thuộc lớp
ArithmeticException, nên chỉ cần bắt đúng lớp này. Các lệnh trong khối try sẽ được
thực hiện lần lượt, cho đến khi ngoại lệ xảy ra thì nhảy sang khối catch tương ứng
với kiểu của ngoại lệ luôn.
-
- Ngoài ra thì cũng có thể lợi dụng upcasting, mọi lớp ngoại lệ có thể bắt được đều là lớp
con của Exception

-
- Ta có thể thêm finally ở cuối. Khối finally sẽ được thực hiện, bất kể có xảy ra ngoại lệ
hay không
-
- Có xảy ra ngoại lệ

-
- Không xảy ra ngoại lệ
-

- Nếu không thích xử lý, có thể ủy nhiệm ngoại lệ. Ví dụ như có 1 loạt các method phục
vụ cho việc kết nối mạng: mở browser, kiểm tra internet, kết nối proxy, gõ link… ở
method nào cũng có khả năng xảy ra ngoại lệ, nhưng đều chỉ có 1 cách xử lý là thông báo
ra màn hình cho người dùng biết để tự đi mà xử lý. Thì ở những method đó ta sẽ ủy
nhiệm ngoại lệ dùng từ khóa throws và throw

- Lưu ý có thể throws nhiều exception, ngăn cách nhau bằng dấu phẩy.
- Khi gọi myMethod, cần phải đưa nó vào trong 1 khối try và bắt tất cả các ngoại lệ nó
throw ra (hoặc bắt mỗi Exception cũng được). Hoặc throws Exception trong cái phương thức
gọi myMethod tiếp (tung đi tiếp, đến khi nào gặp được method đủ thẩm quyền để xử lý)
- E.printStackTrace() sẽ in ra quá trình mà e đã đi qua. Như trên hình, nó thông báo đây là
ngoại lệ thuộc lớp ArithmeticException, kiểu lỗi là / by zero, xuất phát từ method hehe
(dòng 10 – dòng có phép chia), được ném qua hehehe (dòng 14 – dòng gọi đến hehe) và
cuối cùng được ném qua main (dòng 20 – dòng gọi đến hehehe)
- Tạo ngoại lệ tự định nghĩa

You might also like