Java Bài 27: Phương Thức Getter Và Setter – YellowCode.Books

Rate this item :

Rating: 4.7/5. From 67 votes.

Please wait…

Chào mừng các bạn đến với bài học Java thứ 27, bài học về gettersetter. Đây là bài viết trong chuỗi bài về lập trình ngôn ngữ Java của Yellow Code Books.

Bài học hôm nay chúng ta cùng xem qua cách tổ chức các phương thức gettersetter trong Java. Hai phương thức này là gì và chúng có ý nghĩa như thế nào trong việc tổ chức các mối quan hệ giữa các đối tượng trong OOP? Mời các bạn cùng đọc tiếp nhé.

Getter Và Setter Là Gì ?

Đây là hai tên gọi của hai thể loại phương thức. Chúng có liên quan đến đặc tính gói ghém dữ liệu trong lập trình hướng đối tượng, tiếng Anh gọi đặc tính này là Encapsulation. Trước đó, các định nghĩa về khả năng truy cập cũng là một dạng của gói ghém dữ liệu.

Vậy thì gói ghém dữ liệu là gì? Tính gói ghém dữ liệu là một trong những đặc tính cơ bản trong kế thừa, bên cạnh các đặc tính khác, như tính kế thừa (Inheritance) mà bạn đã biết, tính đa hình (Polymorphism) và tính trừu tượng (Abstraction) mà bạn sẽ làm quen sau. Đặc tính gói ghém dữ liệu giúp bao bọc lấy các thuộc tính của một lớp. Nó làm cho các thuộc tính của lớp bị ẩn đi so với các lớp khác.

Vậy getter, setter tương quan gì đến gói ghém tài liệu ? Các phương pháp này giúp cho những thuộc tính private của một lớp hoặc sẽ không hề truy xuất, hoặc chỉ được phép cho đọc ( trải qua phương pháp getter ), hoặc chỉ cho ghi ( trải qua phương pháp setter ) từ những lớp bên ngoài. Đó gọi là gói ghém tài liệu .
Định nghĩa trên chắc đủ rõ ràng cho bạn để hiểu loại phương pháp này đúng không. Nếu chưa thực sự hiểu về nó thì mời bạn đọc tiếp những phần sau nhé .

Tổ Chức Các Phương Thức Getter Và Setter Như Thế Nào ?

Để tạo ra sự gói ghém cho những thuộc tính trong một lớp trải qua getter và setter, bạn làm theo những bước sau .

– Định nghĩa khả năng truy cập cho các thuộc tính trong một lớp về private.
– Xây dựng phương thức getter hay setter cho từng thuộc tính private đó. Với setter bạn nên đặt tên phương thức là setTênThuộcTính(). Còn với getter thì bạn nên đặt tên phương thức là getTênThuộcTính(). Việc xuất hiện của getter và setter cho các thuộc tính private là không bắt buộc. Bạn có thể không cần khai báo bất cứ getter hay setter nào cả nếu như bạn không muốn thuộc tính đó được thấy bởi bất kỳ lớp nào. Hoặc bạn chỉ cần xây dựng getter cho một thuộc tính private nếu bạn muốn thuộc tính đó chỉ được xem, không được sửa chữa. Hoặc chỉ xây dựng setter cho một thuộc tính private nếu bạn muốn thuộc tính đó chỉ có khả năng chỉnh sửa từ bên ngoài mà không được xem.

Nào, để dễ hiểu một chút, chúng ta cùng xem ví dụ ở lớp ToaDo, bạn xem, các thuộc tính x, y ở lớp này được chỉ định private, rồi sau đó nó phải xây dựng thêm các phương thức getter và setter ở bên dưới khai báo thuộc tính.

public class ToaDo {

	private int x;
	private int y;
	
	// getter của thuộc tính x
	public int getX() {
		return x;
	}
	
	// setter của thuộc tính x
	public void setX(int x) {
		this.x = x;
	}
	
	
	// getter của thuộc tính y
	public int getY() {
		return y;
	}
	
	// setter của thuộc tính y
	public void setY(int y) {
		this.y = y;
	}
	
}

Ngay cả với lớp HinhTron hay các lớp hình học khác mà bạn đã biết, chúng ta cũng có thể xây dựng getter và setter cho chúng.

class HinhTron {
	
	private final float PI = 3.14f;
	private float banKinh;
	
	public float getBanKinh() {
		return banKinh;
	}
	
	public void setBanKinh(float banKinh) {
		this.banKinh = banKinh;
	}
	
    public float tinhChuVi() {
        return 2 * PI * banKinh;
    }
 
    public float tinhDienTich() {
        return PI * banKinh * banKinh;
    }
}

Vậy khi gọi đến các phương thức getter và setter này từ bên ngoài lớp sẽ như thế nào. Bạn hãy chú ý vào hàm main() sau đây. Với ví dụ này, mình đã thay thế việc set bán kính hình tròn thông qua constructor, bằng việc gọi đến setter của lớp.

public class MainClass {

	public static void main(String[] args) {
		// Khởi tạo đối tượng hinhTron từ lớp HinhTron
		HinhTron hinhTron = new HinhTron();
		
		// set bán kính cho hinhTron thông qua phương thức setter
		hinhTron.setBanKinh(10);
		
		// Các tính toán khác
		float chuVi = hinhTron.tinhChuVi();
		float dienTich = hinhTron.tinhDienTich();
		System.out.println("Chu vi hình tròn: " + chuVi + "; Và diện tích: " + dienTich) ;
	}
}

Dùng Eclipse Để Khai Báo Getter Và Setter

Bạn có thể thấy rằng, việc đặt tên cho getter và setter của một thuộc tính lớp không có một nguyên tắc cụ thể, chúng nên là getXXX()setXXX(). Vậy thì loạn quá đúng không nào. Tuy nhiên, Eclipse, hay sau này bạn lập trình Android với Android Studio, cũng đều hỗ trợ chúng ta một công cụ tự động phát sinh code getter và setter cho thuộc tính.

Bạn hãy cùng mình thử nghiệm tính năng sinh code tự động hóa qua những bước sau. Lưu ý là nếu bạn thử với Android Studio, hay với những công cụ lập trình Java nào khác, thì mình nghĩ là sẽ tựa như nhau đấy .

Đầu tiên bạn có thể dùng lớp ToaDo, hoặc tạo một lớp bất kỳ trong Eclipse. Bạn hãy khai báo một hay nhiều thuộc tính private cho nó, như sau.

Getter và Setter - Khai báo thuộc tính privateGetter và Setter - Khai báo thuộc tính private

Bạn có thể thấy các icon cảnh báo màu vàng bên thanh trái của editor, tương ứng cho từng thuộc tính private. Vì hệ thống thấy rằng chúng ta khai báo private cho thuộc tính, mà không sử dụng chúng ở bên trong lớp, thì hiển nhiên là có vấn đề rồi, vì bên ngoài lớp có nhìn thấy các giá trị này đâu.

Khi này bạn cứ click vào một trong các cảnh báo này, một dialog nhỏ xuất hiện, bạn hãy chọn vào mục Create getter and setter for ‘tên_thuộc_tính’…. Với dialog xuất hiện tiếp theo sau lựa chọn này, bạn cứ để mặc định rồi nhấn OK là xong.

Getter và Setter - Eclipse gợi ý Getter và SetterGetter và Setter - Eclipse gợi ý Getter và Setter

Bạn hoàn toàn có thể tự kiểm chứng. Kết quả của tùy chọn này giúp bạn tạo ra cả getter và setter cho thuộc tính tương ứng. Bạn cứ làm lần lượt cho những thuộc tính còn lại nhé. Và nếu như bạn muốn bỏ một getter hay một setter nào đó, thì cứ xóa đi phương pháp đó sau khi tạo bởi những bước trên đây .

Getter, Setter Và Những Tùy Biến

Đến đây ắt hẳn bạn đã hiểu getter và setter là gì rồi. Nhưng bạn biết không, những phương pháp getter và setter này không hẳn là được dùng để get hat set tài liệu vào cho thuộc tính của lớp đâu. Bởi vì chúng là những phương pháp, nên bạn trọn vẹn hoàn toàn có thể tận dụng chúng để làm 1 số ít thao tác trước khi get, hay set giá trị .

Mình ví dụ một lớp SinhVien, với đủ thứ các ràng buộc về việc nhập/xuất tên và tuổi như sau. Bạn chú ý để trắc nghiệm kết quả trả về nhé.

public class SinhVien {

	private String ten;
	private String tuoi;
	
	public String getTen() {
		return ten;
	}
	
	public void setTen(String ten) {
		if (ten == null || ten.isEmpty()) {
			// Nếu biến ten chưa khởi tạo (mang giá trị null), hoặc biến ten có nội dung rỗng
			// Thì hãy lưu với tên là "Không biết"
			this.ten = "Không biết";
		} else {
			this.ten = ten;
		}
	}

	public String getTuoi() {
		if (Integer.valueOf(tuoi) != -1) {
			// Tuổi hợp lệ
			return tuoi;
		} else {
			return "Tuổi không hợp lệ";
		}
	}

	public void setTuoi(int tuoi) {
		// Kiểm tra tuổi có hợp lý hay không, nếu hợp lý thì lưu vào, nếu không sẽ tìm cách báo lỗi bằng cách lưu giá trị âm
		if (tuoi > 18) {
			this.tuoi = String.valueOf(tuoi);
		} else {
			this.tuoi = String.valueOf(-1);
		}
	}

}

Với khai báo lớp như trên. Giả sử mình khởi tạo các đối tượng sinh viên này ở hàm main() như sau.

public class MainClass {

	public static void main(String[] args) {
		// Khởi tạo các đối tượng sinhVien
		SinhVien sinhVien1 = new SinhVien();
		SinhVien sinhVien2 = new SinhVien();
		
		// Set thông tin vào cho các sinh viên
		sinhVien1.setTen(""); // Tên không có
		sinhVien1.setTuoi(23);
		
		sinhVien2.setTen("Peter");
		sinhVien2.setTuoi(17);
		
		// In thông tin các sinh viên
		System.out.println("Sinh viên 1 có tên: " + sinhVien1.getTen() + ", tuổi: " + sinhVien1.getTuoi());
		System.out.println("Sinh viên 2 có tên: " + sinhVien2.getTen() + ", tuổi: " + sinhVien2.getTuoi());
	}
}

Bạn thử đoán xem hiệu quả in ra console sẽ như thế nào. Sau đây là tác dụng .

Sinh viên 1 có tên: Không biết, tuổi: 23
Sinh viên 2 có tên: Peter, tuổi: Tuổi không hợp lệ

Vậy là chúng ta vừa xem qua kiến thức về xây dựng các phương thức getter và setter trong hướng đối tượng. Thực sự theo mình thấy, thì getter và setter không cao siêu gì đâu. Chắc chắn khi nhìn vào các ví dụ trên, bạn có thể tự hỏi rằng, hai phương thức này liệu có quan trọng không. Thực ra, cũng đã có nhiều tranh cãi rằng liệu có nên xây dựng getter và setter cho các thuộc tính của lớp trong Java không, hay cứ khai báo public hết cho tất cả các thuộc tính. Vì nhìn chung lại getter và setter sẽ làm cho các lớp trở nên rườm rà hơn. Có một số ý kiến cho rằng hiệu năng của ứng dụng cũng giảm đi với getter và setter. Nhưng như bài học có nói đến, rằng đây là một trong những cách gói ghém dữ liệu của lớp. Với getter và setter, bạn sẽ có thể chỉ định được thuộc tính đó hoàn toàn ẩn, hay chỉ đọc, hay chỉ ghi, hay có thể đọc và ghi. Một cách để làm cho code bạn được tường minh hơn.

Cảm ơn bạn đã đọc những bài viết của Yellow Code Books. Bạn hãy nhìn nhận 5 sao nếu thấy thích bài viết, hãy comment bên dưới nếu có vướng mắc, hãy để lại địa chỉ email của bạn để nhận được thông tin mới nhất khi có bài viết mới, và nhớ san sẻ những bài viết của Yellow Code Books đến nhiều người khác nữa nhé .

Bài Kế Tiếp

Bài tiếp theo đây chúng ta sẽ tìm hiểu về từ khóa static bên trong một lớp nhé.