1. Tính đóng gói (encapsulation) và che giấu thông tin (information hiding) :
- Trong Java, tính đóng gói được thể hiện thông qua phạm vi truy cập (access modifier). Ngoài ra, các lớp liên quan đến nhau có thể được gom chung lại thành package.
- Tính chất này không cho phép người sử dụng các đối tượng thay đổi trạng thái nội tại của một đối tượng. Chỉ có các phương thức nội tại của đối tượng cho phép thay đổi trạng thái của nó. Việc cho phép môi trường bên ngoài tác động lên các dữ liệu nội tại của một đối tượng theo cách nào là hoàn toàn tùy thuộc vào người viết mã. Đây là tính chất đảm bảo sự toàn vẹn, bảo mật của đối tượng,
- Đóng gói là sự che giấu bên trong dữ liệu riêng của mỗi đối tượng của lớp được khai báo và chỉ được truy xuất thông qua hệ thống các phương thức có sẵn của lớp (chỉ có thể gọi những phương thức có sẵn của lớp). Vì vậy, nó còn được gọi là data hiding (nghĩa là che giấu dữ liệu).
- Tính đóng gói có những đặc điểm như sau:
- Tạo ra cơ chế để ngăn ngừa việc gọi phương thức của lớp này tác động hay truy xuất dữ liệu của đối tượng thuộc về lớp khác.
- Dữ liệu riêng (khi được khai báo là
private
) của mỗi đối tượng được bảo vệ khỏi sự truy xuất không hợp lệ từ bên ngoài. - Người lập trình có thể dựa vào cơ chế này để ngăn ngừa việc gán giá trị không hợp lệ vào thành phần dữ liệu của mỗi đối tượng.
- Cho phép thay đổi cấu trúc bên trong của một lớp mà không làm ảnh hưởng đến những lớp bên ngoài có sử dụng lớp đó.
Để cài đặt tính đóng gói, chúng ta có 2 bước như sau:- Khai báo các thuộc tính của đối tượng trong lớp là
private
để các lớp khác không thể truy cập trực tiếp/sửa đổi được. - Cung cấp các phương thức
getter/setter
có phạm vi truy cập làpublic
để truy cập và sửa đổi các giá trị của thuộc tính trong lớp. Phương thứcgetter
là phương thức truy cập vào thuộc tính của đối tượng và trả về các thuộc tính của đối tượng, còn phương thứcsetter
là phương thức truy cập vào thuộc tính của đối tượng và gán giá trị cho các thuộc tính của đối tượng đó. - Ví dụ sau sẽ minh họa tính đóng gói trong Java:123456789101112131415161718192021222324252627282930313233343536
package
vidu;
public
class
Person {
// khai báo các thuộc tính của đối tượng là private
private
String cmnd;
private
String hoTen;
// tạo các phương thức getter/setter
// 2 phương thức getCmnd() và getHoTen() là phương thức getter
// dùng để trả về số chứng minh nhân dân và họ tên của đối tượng
// và kiểu trả về của hai phương thức này tương ứng với kiểu dữ liệu của thuộc tính
// 2 phương thức setCmnd() và setHoTen() là phương thức setter
// dùng để gán giá trị cho thuộc tính chứng minh nhân dân và họ tên của đối tượng
// trong đó tham số truyền vào của 2 phương thức này được gọi là tham số (biến cục bộ)
// và có kiểu dữ liệu tương ứng với kiểu dữ liệu của thuộc tính (biến đối tượng)
public
String getCmnd() {
return
cmnd;
}
// this là từ khóa có ý nghĩa là một tham chiếu đặc biệt
// chiếu tới đối tượng chủ của phương thức hiện hành
// this có thể được dùng để truy cập biến đối tượng (instance variable)
// hoặc gọi phương thức đối với đối tượng hiện hành.
// Thông thường, công dụng này của this chỉ có ích
// khi tên biến đối tượng bị trùng với tham số (biến cục bộ - local variable) của phương thức
public
void
setCmnd(String cmnd) {
this
.cmnd = cmnd;
}
public
String getHoTen() {
return
hoTen;
}
public
void
setHoTen(String hoTen) {
this
.hoTen = hoTen;
}
}
123456789101112131415161718package
vidu;
public
class
TestPerson {
public
static
void
main(String[] args) {
Person person =
new
Person();
// gán giá trị họ tên cho đối tượng person vừa tạo thông qua setHoTen()
// và gán số chứng minh nhân dân thông qua setCmnd()
person.setHoTen(
"Trần Văn Bình"
);
person.setCmnd(
"212321678"
);
// truy cập đến tên của đối tượng person thông qua phương thức getHoten()
// và số chứng minh nhân dân thông qua phương thức getCmnd()
System.out.println(
"Tên: "
+ person.getHoTen() +
", số cmnd: "
+ person.getCmnd());
}
}
Kết quả sau khi biên dịch chương trình: this
là từ khóa có ý nghĩa là một tham chiếu đặc biệt chiếu tới đối tượng chủ của phương thức hiện hành. Trong lớpPerson
, phương thứcsetHoTen()
lấy một tham số (hay còn gọi là biến cục bộ - Local Variable)hoTen
kiểuString
trùng tên với thuộc tínhhoTen
của lớp đó, nếu chúng ta chỉ viết "hoTen
" mà không có từ khóathis
đằng trước thì trình biên dịch sẽ hiểu là ta đang nói đến tham sốhoTen
. Vì vậy, để gọi đến thuộc tính (hay còn gọi là biến đối tượng - Instance Variable), cách duy nhất là sử dụng tham chiếuthis
để gọi một cách tường minh
2.Tính kế thừa (inheritance): - Tư tưởng của kế thừa trong java là có thể tạo ra một class mới được xây dựng trên các lớp đang tồn tại. Khi kế thừa từ một lớp đang tồn tại bạn có sử dụng lại các phương thức và thuộc tính của lớp cha, đồng thời có thể khai báo thêm các phương thức và thuộc tính khác.
- Tính chất này cho phép một đối tượng có thể có được các đặc tính (thuộc tính, phương thức) mà đối tượng khác đã có thông qua kế thừa(extends). Điều này cho phép các đối tượng chia sẻ hay mở rộng các đặc tính sẵn có mà không phải tiến hành định nghĩa lại.
- Tuy nhiên vì tính bao đóng trong Java nên khuyên các bạn chúng ta nên khai báo thuộc tính là private. Java cũng khuyến cáo chúng ta như vậy và tất nhiên các lập trình viên cần phải có ý thức để thuộc tính là private.
- Ở code trên, các bạn thấy rằng chúng ta viết lại y hệt phương thức của class cha, nhưng thây vì phải nhập lại mã , tên sách, thì tôi sẽ dùng từ khóa super để gọi phương thức của lớp cha. Khi chúng ta viết lại phương thức cùng tên,cùng phạm vi truy cập và cùng kiểu dữ liệu trả về của lớp cha. Vậy khi gọi phương thức nhap() cũng như toString() thì nó sẽ chạy phương thức của lớp con.Và loại bỏ phương thức của thằng cha đi
- Vì sao phải ghì đè?
- Để class con đảm bảo đầy đủ các chức năng để nó hoạt động tốt.
- Để đồng bộ code
Vậy theo các bạn phương thức setter và getter trong java có ghì đè được không? Qúa đơn giản, tất nhiên là được vì nó là một hàm bình thường. Tuy nhiên bây giờ theo các bạn, hàm đặc biệt (hàm khởi tạo hay constructor) trong java có ghì đè được không?Trước khi trả lời câu hỏi này, gợi ý các bạn như sau:Constructor là hàm dùng để tạo ra object từ một class nào đấy. (đương nhiên class nào thì đi kèm với constructor của nó).Chắc các bạn có thể dễ dàng đoán ra được rồi với gợi ý của mình rồi chứ? Không nhé.Nếu class SachLapTrinh ghì đè constructor của lớp Sach thì nó quá vô nghĩa và chả có tác dụng gì.Câu hỏi:hàm đặc biệt (hàm khởi tạo hay constructor) trong java có ghì đè được không?Trả lời :Không, nhưng lại có. (trả lời thế nhà tuyển dụng mới sợ nhé).Giải thích như sau:Khi tạo ra object lớp con, thì tất nhiên object lớp cha cũng được khởi tạo.Vì sao? các bạn suy nghĩ lại xem ở ví dụ trên, nếu không tạo ra object lớp cha thì lớp con sao lấy được mã, tên? - Nguyên tắc :Trong constructor của class con khi extends phải gọi constructor của lớp cha, nếu không có constructor thì hệ thống sẽ tự tạo constructor mặc định và gọi constructor của lớp cha.
- super cũng dùng để gọi constructor của lớp cha.Nhưng lại có một trường hợp trơ trêu là constructor của lớp cha không có, hoặc tôi cố tình thay phạm vi truy cập thành private thì điều gì xảy ra? Nó sẽ bị lỗi ngay, vì mặc định hệ thống sẽ gọi constructor của lớp cha, mà constructor lại không có nên đơn nhiên nó bị lỗi.(Các bạn thử thay vào trong code nhé, tôi lười chụp lại ảnh quá).Vậy chúng ta sẽ xử lý như thế nào?
- Các bạn phải tự gọi constructor của lơp cha, một constructor nào đấy nhưng là public nhé. Ví dụ constructor có tham số chẳn hạn.
2. Thông thường thì chúng ta không làm như thế này, mà sẽ làm như sau:làm cách thứ hai thì nhìn vào code rất trong sang và đồng bộ.Tôi nói thêm như vậy để các bạn hiểu bản chất, chứ thật ra chả ai viết ra constructor mà để private cả ^^.
Chưa hết , giả sử như class của lớp cha, không có constructor nào thì điều gì lại xảy ra tiếp theo?Cái này người ta gọi là cấm kế thừa. Một trong những cách cấm kế thừa nữa là ở class các bạn muốn cấm kế thừa thêm vào từ khóa final.Vì sao phải cấm kế thừa? Vì một số trường hợp chúng ta đã viết một số class rất hoản chỉnh rồi và cho người khác sử dụng, tất nhiên đã hoàn chỉnh rồi thì thằng nào muốn dùng thì copy class sử dụng, chứ nếu cho nó kế thừa thì uổng công sức bỏ ra viết quá nhỉ. @@.Lưu ý: Khi kế thừa các bạn phải có ý thức kế thừa chính xác, nghĩa là ví dụ class ConMeo thì không thể extends từ class SinhVat được. Tất nhiên các bạn code thì nó vẫn chạy nhưng sai về mặt ý nghĩa. Chúng ta là lập trình viên thì phải ý thức được điều đấy
3.Tính đa hình (polymorphism):
- Khi một tác vụ được thực hiện theo nhiều cách khác nhau được gọi là tính đa hình.
- Đối với tính chất này, nó được thể hiện rõ nhất qua việc gọi phương thức của đối tượng. Các phương thức hoàn toàn có thể giống nhau, nhưng việc xử lý luồng có thể khác nhau. Nói cách khác: Tính đa hình cung cấp khả năng cho phép người lập trình gọi trước một phương thức của đối tượng, tuy chưa xác định đối tượng có phương thức muốn gọi hay không. Đến khi thực hiện (run-time), chương trình mới xác định được đối tượng và gọi phương thức tương ứng của đối tượng đó. Kết nối trễ giúp chương trình được uyển chuyển hơn, chỉ yêu cầu đối tượng cung cấp đúng phương thức cần thiết là đủ.
- Trong Java, chúng ta sử dụng nạp chồng phương thức (method overloading) và ghi đè phương thức (method overriding) để có tính đa hình.
- đa hình trong phương thức
- Nạp chồng (Overloading): Đây là khả năng cho phép một lớp có nhiều thuộc tính, phương thức cùng tên nhưng với các tham số khác nhau về loại cũng như về số lượng. Khi được gọi, dựa vào tham số truyền vào, phương thức tương ứng sẽ được thực hiện.
- Ghi đè (Overriding): là hai phương thức cùng tên, cùng tham số, cùng kiểu trả về nhưng thằng con viết lại và dùng theo cách của nó, và xuất hiện ở lớp cha và tiếp tục xuất hiện ở lớp con. Khi dùng override, lúc thực thi, nếu lớp Con không có phương thức riêng, phương thức của lớp Cha sẽ được gọi, ngược lại nếu có, phương thức của lớp Con được gọ
- đa hình trong đối tượng:
+ nhìn nhận đối tượng theo nhiều kiểu khác nhau
4.Tính trừu tượng (abstraction):
- Tính trừu tượng là một tiến trình ẩn các chi tiết trình triển khai và chỉ hiển thị tính năng tới người dùng. Tính trừu tượng cho phép bạn loại bỏ tính chất phức tạp của đối tượng bằng cách chỉ đưa ra các thuộc tính và phương thức cần thiết của đối tượng trong lập trình.
- Tính trừu tượng giúp bạn tập trung vào những cốt lõi cần thiết của đối tượng thay vì quan tâm đến cách nó thực hiện.
- Trong Java, chúng là sử dụng abstract class và abstract interface để có tính trừu tượng.
- Ưu điểm khi sử dụng tính trừu tượng để lập trình:
- Tính trừu tượng cho phép các lập trình viên loại bỏ tính chất phức tạp của đối tượng bằng cách chỉ đưa ra các thuộc tính và phương thức cần thiết của đối tượng trong lập trình, cải thiện khả năng bảo trì của hệ thống.
- Tính trừu tượng giúp chúng ta tập trung vào những cốt lõi cần thiết của đối tượng thay vì quan tâm đến cách nó thực hiện.
- Tính trừu tượng cung cấp nhiều tính năng mở rộng khi sử dụng kết hợp với tính đa hình và kế thừa trong lập trình hướng đối tượng.
Nhận xét
Đăng nhận xét