Giới thiệu
Java là 1 ngôn ngữ lập trình thuần hướng đối tượng, không như ngôn ngữ C++ là các thành phần có thể không nằm ngoài, thành phần bất kỳ trong Java phải nằm trong lớp. So với C++ thì OOP trong Java có 1 số điểm khác biệt.
Bài viết này đề cập tới 4 phạm vi truy xuất tương ứng với 4 access modifiers dành cho thuộc tính và phương thức của lớp: private
, default
, protected
, public
.
Access modifiers trong Java
Access modifiers là gì?
Access modifiers là các từ khóa tương ứng với các phạm vi truy xuất vào thuộc tính hoặc phương thức của 1 lớp.
4 Access modifiers trong Java
private
default
protected
public
Phạm vi truy xuất do access modifiers quy định được mô tả chi tiết ở bảng dưới đây:
Trong class | Trong package | class kế thừa trong package | class kế thừa ngoài package | |
---|---|---|---|---|
private |
Được phép | Không được phép | Không được phép | Không được phép |
default |
Được phép | Được phép | Không được phép | Không được phép |
protected |
Được phép | Được phép | Được phép | Không được phép |
public |
Được phép | Được phép | Được phép | Được phép |
Các ví dụ về access modifiers
private
private
: là phạm vi truy xuất thấp nhất, các thuộc tính, phương thức đánh dấu là private chỉ có thể truy xuất trong lớp đó.
Giả sử có lớp Book có 2 thuộc tính là name
và price
.
package com.example.package1; public class Book { private String name; private double price; public Book() { } @Override public String toString() { return "Name: " + name + " - Price: " + price; } }
Và truy cập bên trong lớp cùng package sẽ nhận thông báo lỗi.
package com.example.package1; public class Program { public static void main(String[] args) { Book book = new Book(); book.name = "7 thói quen để thành đạt"; // Lỗi "The field Book.name is not visible" } }
Truy xuất ở lớp kế thừa ngoài package sẽ nhận được lỗi.
package com.example.package2; import com.example.package1.Book; public class FoodBook extends Book { public void print() { System.out.println(this.name); // Lỗi "The field Book.name is not visible" } }
Truy xuất ở lớp không phải lớp kế thừa ngoài package cũng nhận được lỗi tương tự.
package com.example.package2; import com.example.package1.Book; public class OutputHelper { public static void print(Book book) { System.out.println(book.name); // Lỗi "The field Book.name is not visible" } }
default
Mặc định khi khai báo mà không chỉ rõ phạm vi truy xuất thì Java hiểu đó là default
(mặc định), access modifier này được truy cập ở trong class, ở các class cùng package và lớp kế thừa cùng package.
Sửa class Book
bằng cách xóa các từ khóa private
:
package com.example.package1; public class Book { String name; double price; public Book() { } @Override public String toString() { return "Name: " + name + " - Price: " + price; } }
Được phép truy xuất bên trong lớp cùng package.
package com.example.package1; public class Program { public static void main(String[] args) { Book book = new Book(); book.name = "7 thói quen để thành đạt"; // Không lỗi } }
Truy xuất ở lớp kế thừa ngoài package sẽ nhận được lỗi.
Truy xuất ở lớp kế thừa ngoài package xảy ra lỗi.
Truy xuất ở lớp không phải lớp kế thừa ngoài package.
protected
protected
có phạm vi truy xuất rộng hơn default
là có thể truy xuất ở class kế thưa cho dù class đó nằm ngoài hay trong package và không được truy xuất ở các lớp không phải là lớp con ở ngoài package.
Sửa đổi các phạm vi truy xuất của các thuộc tính trong class Book
thành protected
.
package com.example.package1; public class Book { protected String name; protected double price; public Book() { } @Override public String toString() { return "Name: " + name + " - Price: " + price; } }
Và được phép truy cập bên trong lớp cùng package.
package com.example.package1; public class Program { public static void main(String[] args) { Book book = new Book(); book.name = "7 thói quen để thành đạt"; // Không lỗi } }
Cho phép truy xuất ở lớp kế thừa ngoài package.
package com.example.package2; import com.example.package1.Book; public class FoodBook extends Book { public void print() { System.out.println(this.name); // Không lỗi } }
Không cho phép truy cập các lớp không phải lớp con ngoài package.
package com.example.package2; import com.example.package1.Book; public class OutputHelper { public static void print(Book book) { System.out.println(book.name); // Lỗi "The field Book.name is not visible" } }
public
public là phạm vi truy xuất rộng nhất, ở bất kỳ tầm vực nào cũng có thể truy xuất được.
Sửa đổi các trường của class Book
thành public
.
package com.example.package1; public class Book { public String name; public double price; public Book() { } @Override public String toString() { return "Name: " + name + " - Price: " + price; } }
Được phép truy xuất ở lớp trong cùng package
Được phép truy xuất ở lớp kế thừa ngoài package.
Được phép truy xuất ở lớp không phải là lớp kế thừa ngoài package.
Kết luận
Theo nguyên tắc thiết kế hướng đối tượng thì các thuộc tính của class nên để là private và truy cập thông qua các phương thức getter/setter. Nếu để chúng public sẽ phá vỡ nguyên tắc đóng gói của hướng đối tượng.