[Java] Các mức truy cập trong java – Modifier in Java

Để bảo vệ dữ liệu tránh bị truy nhập tự do từ bên ngoài, lập trình hướng đối tượng sử dụng các từ khoá quy định phạm vi truy nhập các thuộc tính và phương thức của lớp. Java sử dụng một số bổ ngữ sau để kiểm soát việc truy nhập các thành phần của đối tượng :

  • public: Thành phần công khai, truy nhập tự do từ bên ngoài.
  • protected: Thành phần được bảo vệ, được hạn chế truy nhập.
  • mặc định (không viết gì): Truy nhập trong nội bộ gói.
  • private: Truy nhập trong nội bộ lớp.

1. Các thành phần public

Thành phần public là khu vực mà Lớp có thể chia sẻ với tất cả các chương trình và đối tượng bên ngoài. Thành phần public có thể được truy nhập từ bên trong lẫn bên ngoài lớp:

Ví dụ: ta có cấu trúc 2 gói như sau:

public trong java
Trong đó nội dung các file của chúng ta như sau:
* file ClassA1.java nằm trong gói GoiA có các thành phần (biến varA1 và phương thức methodA1) là công khai (public):

package GoiA;				// goi ten la GoiA

public class ClassA1 {
	public int varA1 = 5;		// bien cong khai ten la varA
	public void methodA1(){		// phuong thuc cong khai methodA1
		System.out.println("methodA1 trong ClassA1 la public");
	}
}

* file ClassA2.java nằm trong gói GoiA gồm 1 phương thức methodA2 sử dụng được các thành phần của ClassA1.

package GoiA;			// goi GoiA

public class ClassA2 {		// ClassA2 su dung bien va phuong thuc cua ClassA1
	void methodA2(){		// phuong thuc methodA2 goi cac thanh phan cua ClassA1
		ClassA1 a1 = new ClassA1();		// tao doi tuong a1 thuoc lop ClassA1
		a1.methodA1();					// goi phuong thuc methodA1
		System.out.println("Bien varA1 = " + a1.varA1);		// in bien varA1
	}
}

* file ClassA3.java cũng nằm trong GoiA kế thừa và sử dụng được các thành phần của ClassA1

package GoiA;

public class ClassA3 extends ClassA1{	// ClassA3 ke thua ClassA1
	void methodA3(){					// phuong thuc methodA3 goi methodA1()
		methodA1();
	}
}

Chuyển sang gói GoiB ta có 2 file:
* file ClassB1.java cũng gọi các thành phần của ClassA1 giống như file ClassA2 tuy nhiên do ClassB1 nằm khác gói với ClassA1 nên chúng ta cần import nó.

package GoiB;

import GoiA.ClassA1;		// import ClassA1 de su dung

public class ClassB1 {
	void methodB1(){		// phuong thuc methodB1 goi cac thanh phan cua ClassA1
		ClassA1 a1 = new ClassA1();		// tao doi tuong a1 thuoc lop ClassA1
		a1.methodA1();					// goi phuong thuc methodA1
		System.out.println("Bien varA1 = " + a1.varA1);		// in bien varA1
	}
}

* file ClassB2.java cũng kế thừa được ClassA1 giống như ClassA3 kế thừa ClassA1 nhưng cần phải import ClassA1 vào.

package GoiB;

import GoiA.ClassA1;

public class ClassB2 extends ClassA1{	// ClassB2 ke thua ClassA1
	void methodB2(){					// phuong thuc methodB2 goi methodA1()
		methodA1();
	}
}

Như vậy chúng ta có thể thấy được tính công khai ở mọi nơi của ClassA1 khi ta dùng bổ ngữ public.
Ta có thể rút ra nhận xét nhanh bằng hình ảnh minh họa sau:
khả năng truy nhập public

2. Các thành phần protected

Tất cả các lớp trong gói chứa nó và tất cả các lớp kế thừa nó (bao gồm cả các lớp kế thừa từ các gói khác) sẽ truy cập được tới nó.

Cũng với VD như trên, chúng ta có 2 gói là GoiA và GoiB cùng với các class đó, chỉ thay đổi ClassA1 với các thành phần protected như sau (các ClassA2, ClassA3, ClassB1, ClassB2 vẫn giữ nguyên):

*flie ClassA1.java

package GoiA;				// goi ten la GoiA

public class ClassA1 {
	protected int varA1 = 5;		// bien protected ten la varA
	protected void methodA1(){		// phuong thuc protected methodA1
		System.out.println("methodA1 trong ClassA1 la public");
	}
}

Khi đó các lớp ClassA2, ClassA3 vẫn truy cập được vào các thành phần của ClassA1 vì nó nằm cùng gòi GoiA với ClassA1, ClassB2 cũng truy cập được vì tuy khác gói nhưng nó kế thừa ClassA1. Tuy nhiên ClassB1 thì không thể truy nhập được.

*flie ClassB1.java

package GoiB;

import GoiA.ClassA1;		// import ClassA1 de su dung

public class ClassB1 {
	void methodB1(){		// phuong thuc methodB1 goi cac thanh phan cua ClassA1
		ClassA1 a1 = new ClassA1();
		a1.methodA1();										// loi truy nhap
		System.out.println("Bien varA1 = " + a1.varA1);		// loi truy nhap
	}
}

ClassB1 bị lỗi
protected
Nhận xét:
khả năng truy nhập protected

3. Các thành phần default

Các thành phần mặc định (không khai báo gì) thì chỉ cho phép các lớp trong cùng 1 gói truy nhập tới (kể cả khi kế thừa). Mọi sự truy nhập hoặc kế thừa từ các gói khác đều không được.

Tương tự, với ví dụ trên ta để các thành phẩn của ClassA1 là default, khi đó ClassB1 và ClassB2 đều bị lỗi vì nó không nằm trong cùng gói với ClassA1.
* file ClassA1.java

package GoiA;				// goi ten la GoiA

public class ClassA1 {
	int varA1 = 5;		// bien mac dinh ten la varA
	void methodA1(){		// phuong thuc mac dinh methodA1
		System.out.println("methodA1 trong ClassA1 la public");
	}
}

*flie ClassB1.java

package GoiB;

import GoiA.ClassA1;		// import ClassA1 de su dung

public class ClassB1 {
	void methodB1(){		// phuong thuc methodB1 goi cac thanh phan cua ClassA1
		ClassA1 a1 = new ClassA1();
		a1.methodA1();										// loi truy nhap
		System.out.println("Bien varA1 = " + a1.varA1);		// loi truy nhap
	}
}

*flie ClassB2.java

package GoiB;

import GoiA.ClassA1;

public class ClassB2 extends ClassA1{	// ClassB2 ke thua ClassA1
	void methodB2(){					// phuong thuc methodB2 goi methodA1()
		methodA1();						// loi truy nhap
	}
}

ClassB1, ClassB2 đều bị lỗi mặc dù ClassB2 chúng ta có thể khai báo là extends ClassA1 nhưng cũng không sử dụng được các thành phần của ClassA1.
default

Nhận xét:
khả năng truy nhập default

4. Các thành phần private

Các thành phần riêng tư được bảo vệ chặt chẽ nhất, chỉ có các đối tượng trong cùng 1 lớp mới truy nhập được, mọi sự truy nhập hay kế thừa từ các lớp khác ngay cả khi các lớp đó trong cùng 1 gói cũng không truy nhập được.

private

*flie ClassA1.java

package GoiA;				// goi ten la GoiA

public class ClassA1 {
	private int varA1 = 5;			// bien private ten la varA
	private void methodA1(){		// phuong thuc private methodA1
		System.out.println("methodA1 trong ClassA1 la public");
	}

	void methodA2(){
		methodA1();										// goi phuong thuc methodA1
		System.out.println("Bien varA1 = " + varA1);	// in bien varA1
	}
}

Chúng ta thấy chỉ có phương thức methodA2() nằm cùng Class với các thành phần private của ClassA1 mới có thể truy nhập, ngay cả ClassA2, ClassA3 nằm cùng gói GoiA cũng không thể truy nhập.

Nhận xét:
khả năng truy nhập private

Như vậy ta có thể thấy khả năng truy nhập của các thành phần public, protected, default, private giảm dần đồng nghĩa với khả năng bảo mật thông tin tăng dần. Ta có thể có một sự tổng kết nho nhỏ sau:

modifier

Bài viết có sự tham khảo của:
– Giáo trình lập trình hướng đối tượng Java – Đoàn Văn Ban
– Giáo trình lập trình hướng đối tượng Java – Trần Đình Quế
naynhoanhthichem.blogspot.com
Và một số giáo trình, website khác.