Chương 3. LẬP TRÌNH HƯỚNG ĐỔI TƯỢNG
3.1.4. Khai báo và sử dụng phương thức của lớp
Hàm hay phương thức của lớp trong Java là khối lệnh thực hiện các chức năng, các hành vi xử lý của lóp lên các thành phần dữ liệu. Phương thức của lớp đượckhai báo theo cú pháp:
<ti'ên tố> <kiêìi trả v'ê><tên phương thức> [[<các tham số>]) [throws <các ngoạilệ>]
{
<khốilệnh>;
}
Trong đó:
- Tiềntố: đặc trưng bởi các từ khóa tương tự như tiền tố của thuộc tính. Giátrị mặc định là public.
- Kiểu trả về: Kiểudữ liệu trảvề củaphương thức, có thể là kiểu dữ liệu sẵn có của Javahoặc là kiếu do người dùng tự định nghĩa.
- Tên phương thức: tuân theo quitắc đặt tên biếncủa Java.
- Các ngoại lệ: là một đối tượng đặc biệt được tạo ra khi chương trình gặp lỗi. Java sẽ trả lại cho chương trình ngoại lệ này theo từ khóa throws. Các ngoại lệ, nếu có, được phân cách nhau bởi dấu phẩy.
- Các tham số: các tham số của phương thức, được liệt kê theo cặp <kiểu tham số>
<tên tham số>, các tham số được phân biệt bởi dấu phẩy.
Lưu ý là thông thường trong một lớp, các phương thức nên được khai báo dùng từ khóapublic, khác với thành phầndữliệu thường là dùngtiềntoprivatevì mục đích an toàn.
Ví dụ dưới đây mô tả việc khai báo phương thức tinhgiaban() để tính và trả về giá bán của chiếc xe máy.
package vidu.chuong3;
class Xemay ỉ
public Stringnhasx;
public String model;
private float chiphisx;
protected int thoigiansx;
//sobanhxe là biến tĩnh cógiá trịlà 2 trong tất cả // cácthể hiện tạo ro từ lớp Xemay
public static int sobanhxe =2;
public float tinhgiaban() {
return 2 * chiphisx;
} }
Phương thức tinhgiaban() tính và trả về giá bán của chiếc xemáy dựa trên giá trị biến chiphisx của đối tượng thuộc lớp Xemay. Biến này trong các đối tượng khác nhau thường có giá trị khác nhau, nên giá trị trả về của hàm tinhgiaban() cho các đối tượng cũng khác nhau.
Để truy cập các thuộc tính cũng như gọi phương thức của một đối tượng, chúng ta sử dụng toán tử dấu chấm (.). Cụ thế: Saukhi đối tượng myObj được tạo ra (bằng lệnh Xemay myObj = new XemayO;), lệnh myObj.nhasx = “Honda” sẽ gán giá trị “Honda” cho biến nhasx của đối tượng myObj, còn lệnh myObj.tinhgiaban() sẽ kích hoạt phương thức tinhgiaban() của myObj.
Khi sử dụng phương thức, chúng ta cần lưuý một số điểm quan trọng sau đây:
- Một phương thức có thể có các tham số. Ta có thể truyền các giá trị vào phương thức qua các tham số của phương thức.
- Số lượng và kiểu dữ liệu của các giá trị ta truyền vào phương thức (đối số) phải khớp với thứ tự và kiếu dữ liệucủa các tham số được khai báo của phương thức.
- Các giá trị truyền vào phương thức hoặc được trả về từ phương thức có thể được ngầm đổi từ kiểu hẹp hơn sang kiểu rộng hơn, hoặc phải được đổi tường minh sang kiểu hẹp hơn.
- Các giá trị dùng làm đối số có thể là một giá trị trực tiếp (1, ’d’,...) hoặc một biến hay biểu thức có giá trịthuộckiểu đãđược khai báo cho tham số.
- Một phương thức phải có kiếu trả về. Kiếu trả về void có nghĩa phương thức không trả về giá trị gì. Neu không, phương thức phảitrả về một giá trị tương thích với kiểu trả về đã khai báo.
3.1.5. Phương thức khởi tạo của lớp
Phương thức khởi tạo thật ra là một loại phương thức đặc biệt của lớp. Phương thức khởi tạo dùng gọi tự động khi khởi tạo một thể hiện của lớp, có thể dùng để khởi gán những giá trị măc định. Các phương thức khởi tạo không có giá trị trả về và có thế có tham số hoặc không có tham số.
Phương thức khởi tạo phải có cùng tên với lớp và được gọi đến dùng từ khóa new.
Có thể có nhiều phương thức khởi tạo của cùng một lớp.
Neu một lớp không có phương thức khởi tạo thì Java sẽ cung cấp cho lớp một phương thức khởi tạo mặc định. Những thuộc tính, biến của lóp sẽ được khởi tạo bởi các giá trị mặc định (số: thường là giá trị 0, kiểu luận lý làgiá trị false, kiểu đối tượng giá trị null,...). Tuy nhiên, nếu trong lớp đã có ít nhất một phương thức khởi tạo thì phương thức khởi tạo mặc định sẽ không được tạo ra, khi ta tạo ra một đối tượng thì sẽ có một phương thức khởi tạo nào đó được gọi, nếu trình biên dịch không tìm thấy phương thức khởi tạo tương ứng nó sẽ thông báo lồi. Điều này thường xảy ra khi chúng ta không xây dựng
phương thức khởi tạo không tham số nhưng khi khởi tạo đối tượng ta lại không truyền vào đối số. Do vậy thông thường để an toàn, dễ kiểm soát và làm chủ mã nguồn chương trình, chúng ta nên luôn khai báo phương thức khởi tạo mặc định và cácphương thức khởi tạocó tham số cho lóp.
Chương trình 3.1 minh họa phương thức khởitạo mặc định và phương thức khởi tạo nhiều tham số của lớp Xemay bằng cách gán giá trị cho cácthuộc tính của lớp.
Chương trình 3.1
package vidu.chuong3;
class Xemay {
//...
public XemqyfJ {}
public Xemay (String nhasxl, String modell, float chiphisxl, int thoigiansxl) {
nhasx = nhasxl;
model= modell;
chiphisx = chiphísxl;
thoigiansx = thoigiansxl;
} }
Chương trình 3.2 minh họa cách dùng lớp Xemay mà chúng ta vừa định nghĩa trong chương trình 3.1. Chương trình này sẽ tạo ra một đối tượng xel của lóp Xemay với các thuộc tính có giá trị khởi tạo: nhasx = ’’Honda”, model = "SH150Ì”, chiphisx = 1095 và thoigiansx = 2010. Sau đó, chương trình inra giá bán chiếc xe bằng việc sử dụng phương thức tinhgiabanO củađối tượng xel.
Chương trình 3.2 package vidu.chuong3;
public class XemayDemo {
public static void mainfString args[]) {
Xemayxel = newXemayf'Honda", "SH150Ĩ", 1095,2010);
System.out.println(”Gia ban la $” + xel. tinhgiabanQ);
} }
Kết quả thực hiện chương trình:
Gia ban la $2190.02 3.1.6. Biến this
Biến this là một biến ẩn đặc biệtluôntồn tại trong các lóp Java: một lóp có đúng một biến ẩn this. Biến này được sử dụng trong khi chạy và nó trỏ đến bản thân lóp chứa nó.
Bien this thường được sử dụng trong các hàm khởi tạo của lóp.
Chương trinh 3.3 khai báo một lóp hoàn toàn giống với lóp được khai báo trong chương trình 3.1, nhưng chỉ khác là có dùngbiến this tronghàm khởi tạo của lớp.
Chương trình 3.3 package vidu.chuong3;
class Xemay {
//...
publicXemayQ {}
public XemayfStringnhasx, String model, float chiphisx, intthoigiansx) {
this.nhasx = nhasx;
this.model= model;
this.chiphisx= chiphisx;
this.thoigicmsx =thoigiansx;
}
Trong chương trình 3.3, ta chú ý đến hàm khởi tạo nhiều tham số của lóp, hàm này có bốn tham số là nhasx, model, chiphisx và thoigiansx trùng với các biến của lóp. Do đó, trong phạm vi hàm này, biến this.nhasx, this.model, this.chiphisx và this.thoigiansx sẽ chỉ các biến của lóp, còn các tham số nhasx, model, chiphisx và thoigiansx sẽ chỉ các biến cục bộ củahàm. Cho nên, các lệnh gán vẫn thực thi như trong chương trình 3.1.
3.1.7. Khai báo chồng phương thức
Việc khai báo trong một lớp nhiều phương thức có cùng tên nhưng khác tham số (khác kiểu dữ liệu, khác số lượng tham số) gọi là khai báo chồng phương thức (overloading method).
Ví dụ:
package vidu.chuong3;
classXemay {
//khaibáo cácthuộc tính ...
public float tinhgiabanf) {
return 2 * chiphisx;
}
public float tinhgiabanffloat huehong) {
return (2 * chiphisx + huehong);
} }
3.1.8. Cácthành phần tĩnh
3.1.8.1. Thuộctinh tĩnh
Đôi khi bạn muốn có một thuộc tính (biến) được chia sẻ giữa tất cả các đối tượng của một lớp. Ví dụ, bạn muốn cómột biến để đếm số lần một hàm thànhviên được gọi bởi tất cả các đối tượng của lóp. Những thuộc tính như vậy được gọi làthuộc tính tĩnh và chúng có thế được sử dụng để các đối tượng có thể giao tiếphoặc phối họp hành động với các đối tượng khác.
Thuộc tính tĩnh được khai báo với từ khóa static. Cũng chú ý rằng chúng thường được khởi tạo khi khai báo.
Ví dụ:
class Static{
static int i = 10;
intj = 10;
//Đây là thuộctính tĩnh //Đây là thuộctínhthường }
Các thuộc tính tĩnh được cấpphát một vùng bộ nhớ cố định, trong Java, bộ nhớ dành cho các thuộc tính tĩnh chỉ được cấpphátkhi lần đầu tiênta truy cập đến nó.
Thuộc tính tĩnh (cũng như phương thức tĩnh) là chung của cả lớp, nó không là của riêngmột đối tượng nào cả. Nên đế truy xuất đến thuộc tínhtĩnh ta có thể dùng một trong hai cách sau:
<tên lớp>.<tên thuộctínhtĩnh>;
<tên đốitượng>.<tên thuộctínhtĩnh>;
Cả hai cách truy xuất trên đều có tác dụng như nhau.
Chú ý rằng ta không thể sử dụnghàm tạo để khởi đầu các thuộc tính tĩnh, bời vì hàm tạo không phải là phương thức tĩnh.
3.1.8.2. Phương thức tĩnh
Neu một phương thức không truy cập đến dữ liệu của bất kỳ một đối tượng nào và bạn vẫn muốn phương thức này là một thành viên của lớp thỉ bạn có thể làm cho nó trở thành phương thức tĩnh. Phương thức tĩnh có thể được gọi theo thông qua đối tượng của lớp. Tuy nhiên thông thường thì phương thức tĩnh được gọithông qua tên lớp.
Một phương thứctĩnh được khai báo bằngtừkhóa static. Phương thứctĩnh là chung cho cảlóp, nó không lệ thuộc vào một đối tượng cụ thế nào.
Ví dụ:
class Static{
static int i;// Đâylà thuộc tínhtĩnh // phương thứctĩnh
static void printin 0{
System.outprintln (i);
} }
Lời gọiphương thức tĩnh xuất phát từ:
-Tên của lóp:
<tên lớp>.<tên phương thứctĩnh>(thamsố);
- Tên của đối tượng:
<tên đốitượng>.<tên phương thức tĩnh>(tham số);
Vì phương thức tĩnh là độc lập với đối tượng, do vậy ở bên trongphương thức tĩnh ta không thể truy cập các thành viên không tĩnh củalóp đó, tức là bên trong phương thức tĩnh ta chỉ có thể truy cập đến các thành viên tĩnh mà thôi. Cũng lưu ý rằng ta không thể sử dụng từ khóa this bên trong phương thức tĩnh.
Chương trình 3.4 trình bày một minh họa vềthuộc tính tĩnh và phương thức tĩnh:
Chương trình 3.4 class Student{
int rollno;
String name;
static Stringcollege= "BachKhoa";
static void change(){
college= ”Thuy Loi";
}
Student(intr, String n){
rollno = r;
name = n;
}
void display (){System.out.println(rollno + " " + name+ " - " + college);}
publicstaticvoidmainfString args[]){
Student si =new Student (111,"Hoang");
Students2 =new Student (222,"Thuy");
sl.displayO;
s2.display();
Student.change();
sl.displayO;
s2.display();
} }
Kết quả thực hiện chương trình:
111 Hoang- Bach Khoa 222 Thuy - Bach Khoa 111 Hoang- Thuy Loi 222 Thuy - Thuy Loi
3.1.9. Phương thức finalize()
Trong Java không có kiểu dữ liệu con trỏ như trong c, người lập trình không cần phải quá bận tâm về việc cấp phát và giải phóng vùng nhớ, sẽ có một trình dọn dẹp hệ thống đảm trách việc này. Trình dọn dẹp hệ thống sẽ dọn dẹp vùng nhớ cấp phát cho các đốitượng trước khi hủy một đối tượng.
Phương thức fìnalize() là một phương thức đặc biệt được cài đặt sẵn cho các lóp.
Trình dọn dẹp hệthống sẽ gọi phương thứcnày trước khi hủy một đối tượng. Vì vậy, việc cài đặt một số thao tác giải phóng, dọn dẹp vùng nhớ đã cấp phát cho các đối tượng dữ liệu trong phương thức fínalize() sẽ giúp cho người lập trình chủđộng kiếm soáttốt quá trình hủy đối tượng thay vì giao cho trình dọn dẹp hệ thống tự động. Đồng thời việc cài đặt trong phương thức fmalize() sẽ giúp cho bộ nhớ được giảiphóng tốt hơn, gópphần cải tiến tốc độ chươngtrình.
Ví dụ:
classA
//Khai báocác thuộc tính public void method-1 ()
protectedvoid finalize()
// Có thể dùng để đóng tấtcả các kết nối // vào cơ sở dữ liệu trướckhi hủy đối tượng.
3.2. ĐẶC ĐIÊM HƯỚNG ĐỐI TƯỢNG TRONG JAVA
HỖ trợ những nguyên tắc cơ bản của lập trình hướng đối tượng, tất cả các ngôn ngữ lập trình kể cả Java đều có bốnđặc điểm chung: tính đóng gói (encapsulation), tính đahình (polymorphism), tính kế thừa (inheritance) và tính trừu tượng (abstraction).
-Tính đóng gói (encapsulation) và che giấu thông tin (information hiding):
Tức là trạng thái của đối tượng được bảo vệ không cho các truy cập từ code bên ngoài như thay đối trạng thái hay nhìn trực tiếp. 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 đảmbảo sự toàn vẹn, bảo mật của đối tượng. 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ớpliên quan đến nhau có thể được gom chung lạithành package.
- Tính kế thừa là khả năng cho phép ta xây dựng một lớp mới dựa trên các định nghĩa của một lóp đã có. Lóp đã có gọi là lóp cha, lóp mới phát sinh gọi là lóp con và đương nhiên kế thừa tất cả các thành phần của lớp cha, có thể chia sẻ hay mởrộng các đặc