Tại sao Java xác định rằng trình chỉ định truy cập cho một phương thức ghi đè có thể cho phép nhiều hơn, nhưng không ít hơn, truy cập so với phương pháp ghi đè? Ví dụ, một phương thức cá thể được bảo vệ trong siêu lớp có thể được công khai, nhưng không phải là riêng tư, trong lớp con.Các công cụ sửa đổi truy cập java và các phương thức ghi đè
Trả lời
Đó là một nguyên tắc cơ bản trong OOP: lớp trẻ là một trường hợp hoàn toàn chính thức của lớp cha mẹ, và phải do hiện ít nhất cùng một giao diện làm lớp cha. Làm cho những điều được bảo vệ/công khai ít hiển thị hơn sẽ vi phạm ý tưởng này; bạn có thể làm cho các lớp con không sử dụng được như các cá thể của lớp cha.
Đồng ý với Patrick. Điều này cũng theo nguyên tắc thay thế Liskov – tapasvi
Bởi vì nó sẽ là kỳ lạ:
class A {
public void blah() {}
}
class B extends A {
private void blah() {}
}
B b = new B();
A a = b;
b.blah(); // Can't do it!
a.blah(); // Can do it, even though it's the same object!
Tôi nghĩ rằng trước khi bạn thay đổi nó là một ví dụ cụ thể hơn, mặc dù điều này hơi khó chịu hơn, vì bạn có thể định nghĩa một trường hợp như vậy để ném một ngoại lệ thời gian chạy khi truy cập một phương thức riêng tư (rõ ràng là một thuật ngữ được phát minh). Nhưng trong ví dụ trước của bạn người ta sẽ phải làm việc, và người kia phải thất bại. Có thể bao gồm cả hai? – davin
@davin: Tôi chưa thay đổi! Tôi chỉ cải thiện nhận xét mã ... –
Ồ, sau đó tôi tưởng tượng rằng bạn có 'A a = new A(); B b = new B(); 'hoặc' A b = new B(); ' – davin
Hãy tưởng tượng hai loại cổ phiếu này:
public class Animal {
public String getName() { return this.name; }
}
public class Lion extends Animal {
private String getName() { return this.name; }
}
tôi có thể viết mã này:
Animal lion = new Lion();
System.out.println(lion.getName());
Và nó sẽ phải có giá trị, kể từ ngày Động vật phương thức getName() là công khai, ngay cả khi nó được đặt ở chế độ riêng tư trên Lion. Vì vậy, không thể làm cho mọi thứ ít hiển thị hơn trên các lớp con như khi bạn có một tham chiếu siêu lớp, bạn sẽ có thể truy cập vào nội dung này.
Bạn đang thiếu một 'mở rộng động vật' :) – Jeffrey
có vẻ là một câu trả lời tốt hơn. – instinct
Đây là nguyên tắc thay thế của Liskov. – RainDoctor
Vì một lớp con là một chuyên môn của lớp cha hoặc nói cách khác, đó là phần mở rộng của lớp cha.
Hãy tưởng tượng ví dụ phương pháp toString. Tất cả các đối tượng Java đều có nó vì Object của lớp có nó. Hãy tưởng tượng bạn có thể định nghĩa một lớp với phương thức toString là private. Sau đó bạn không còn đối xử với tất cả các đối tượng như nhau nữa. Ví dụ, bạn sẽ không còn có thể một cách an toàn này:
for (Object obj : collection) System.out.println(obj);
Vâng, về trường hợp cụ thể bạn đã đề cập, Java sẽ xử lý chính xác điều đó như thế nào? Nếu lớp con tạo một phương thức public/protected private, thì JVM nên làm gì khi phương thức đó được gọi trên một cá thể của lớp con? Tôn trọng riêng tư và gọi triển khai của lớp cha? Hơn nữa, bạn đang phá vỡ hợp đồng được chỉ định bởi các siêu lớp khi bạn đột nhiên nói "không ai có thể truy cập phương pháp này, mặc dù những gì hợp đồng ban đầu nói."
Lấy một ví dụ đưa ra dưới đây
class Person{
public void display(){
//some operation
}
}
class Employee extends Person{
private void display(){
//some operation
}
}
trọng điển hình xảy ra trong trường hợp sau đây
Person p=new Employee();
Đây p
là tài liệu tham khảo đối tượng với kiểu Person (siêu lớp) khi chúng ta đang kêu gọi p .display(). Khi sửa đổi lần truy cập là hạn chế hơn, các tài liệu tham khảo đối tượng p
không thể truy cập đối tượng con của loại nhân viên
muộn để đảng nhưng tôi muốn thêm một người nữa mối quan tâm liên quan đến trọng: Phương pháp trọng phải cho phép ít (hoặc cùng một mức độ) ngoại lệ ném được so với phương pháp ghi đè; thậm chí không có gì ném được.
Liskov nguyên tắc thay thế có thể giải thích rằng quá:
interface Actionable {
void action() throws DislocationException;
}
public class Actor implements Actionable {
@Override
public void action() throws DislocationException {
//....
}
}
public class Stuntman implements Actionable {
@Override // this will cause compiler error
public void action() throws DislocationException, DeathException {
//....
}
}
// legacy code to use Actionable
try {
Actionable actor = new Actor(); // this cannot be replaced by a Stuntman,
// or it may break the try/catch block
actor.action();
} catch (DislocationException exc) {
// Do something else
}
Ở trên, phương pháp ghi đè đưa ra cam kết rằng trong trường hợp xấu nhất nó sẽ ném DislocationException, không còn phải (một bác sĩ là cần thiết tại địa điểm quay phim) . Vì vậy, phương pháp ghi đè không được phá vỡ điều đó, bằng cách thêm nhiều DeathException (hoặc xe cứu thương là phải)
Tôi thường gọi quy tắc ghi đè "[có thể] thêm quyền truy cập [cấp độ], [nhưng] ít ngoại lệ"
- 1. Thay đổi công cụ sửa đổi truy cập của một phương thức ghi đè trong Java?
- 2. Các công cụ sửa đổi truy cập có quan trọng đối với phương thức chính không?
- 3. Sự khác biệt giữa các thông số truy cập và các công cụ sửa đổi truy cập là gì?
- 4. Mục đích của phương pháp này để truy cập các công cụ sửa đổi là gì?
- 5. Thông số truy cập trong khi các phương pháp ghi đè
- 6. Các công cụ sửa đổi truy cập có ảnh hưởng đến sự phản chiếu không?
- 7. Các công cụ sửa đổi truy cập trên các thành viên giao diện trong C#
- 8. việc sử dụng các phương thức công khai khi lớp có trình sửa đổi truy cập mặc định là gì?
- 9. Ghi đè phương thức ghi đè (C#)
- 10. Các công cụ sửa đổi truy cập bên trong một lớp lồng nhau tĩnh riêng trong Java
- 11. Công cụ sửa đổi truy cập tự động Refactor
- 12. Các lớp lồng ghép Java địa phương và truy cập các phương thức siêu
- 13. Truy cập các phương thức "Công khai" từ các phương thức "Riêng tư" trong lớp javascript
- 14. Truy cập các phương thức dll trong java
- 15. Phương pháp truy cập phản xạ Java với công cụ sửa đổi mặc định trong lớp siêu
- 16. Thay đổi vùng tên tệp (resx) và công cụ sửa đổi truy cập
- 17. Ghi đè đăng ký ghi đè Tạo Phương thức
- 18. Truy cập phương thức java tĩnh công cộng từ scala
- 19. Java Swing: Mở rộng các phương thức DefaultComboBoxModel và ghi đè
- 20. Sự khác biệt giữa các công cụ sửa đổi biểu thức chính quy 'm' và 's'?
- 21. Cách "ghi đè" các phương thức mở rộng trong .NET?
- 22. Tại sao một chức năng với công cụ sửa đổi được bảo vệ có thể bị ghi đè và truy cập mọi nơi?
- 23. Các phương pháp ghi đè trong JavaDoc
- 24. Ghi đè các phương thức liên quan của Django
- 25. Ghi đè phương thức gửi của XMLHttpRequest
- 26. phương pháp mà không cần sửa đổi truy cập
- 27. Ghi đè phương thức truy cập mặc định trên các trình nạp lớp khác nhau phá vỡ đa hình
- 28. Cách kiểm tra các trường riêng được sửa đổi thông qua các phương thức công cộng
- 29. C# Ghi đè phương thức GetHashCode
- 30. Làm cách nào và ở đâu để sử dụng công cụ sửa đổi tĩnh trong Java?
Để sử dụng mô tả chung: 'B mở rộng A' nếu' B là A '. Vì vậy, nếu 'A' có thể thực hiện' action() ', và' B là a', thì 'B' cũng có thể thực hiện' action() '. – davin
cảm ơn tất cả các bạn. Bây giờ tôi hiểu rằng việc khai báo mở rộng (A mở rộng B) cũng tạo ra một lược đồ kế thừa truy cập một chiều (mở rộng hơn). – yesilupper