Vâng, tôi nghĩ bạn đúng. Tùy chọn thứ hai chỉ liên quan đến một trường hợp cụ thể: phân lớp cụ thể nằm trong một gói khác với gói siêu lớp của nó.
Ví dụ,
package superpackage;
public abstract class SuperFoo {
abstract void foo();
}
package subpackage;
import superpackage.SuperFoo;
public abstract class SubFoo extends SuperFoo {}
Xin lưu ý rằng lớp này cần được khai báo trừu tượng, nếu không chúng tôi có lỗi biên dịch.
Trong trường hợp cụ thể này, chúng tôi không có "kế thừa phương pháp foo" vì kế thừa yêu cầu lớp SubFoo nằm trong cùng gói với SuperFoo. xem phần 8.4.8 trong JLS để biết thêm chi tiết.
Tuy nhiên, lớp này vẫn chứa phương pháp "foo" (theo định nghĩa) và do đó nên được đánh dấu với từ khóa trừu tượng.
Hơn nữa, chúng ta có thể mở rộng lớp SubFoo của chúng tôi bằng một lớp bê tông thuộc về "superpackage" gói.
Ví dụ,
package subclass;
import subpackage.SubFoo;
public class SecondSubFoo extends SubFoo {
@Override
void foo() {}
}
Lưu ý:
1) Thực tế là phương pháp công cộng và bảo vệ rơi vào mục đầu tiên của định nghĩa khi chúng được kế thừa và không cần mục thứ hai của định nghĩa cho chúng.
2) Các phương thức truy cập gói cũng rơi vào mục đầu tiên của định nghĩa nếu chúng nằm trong cùng một gói và do đó không cần mục thứ hai của định nghĩa cho chúng nữa. Mặt khác, các phương thức truy cập gói nằm trong gói khác không rơi vào mục đầu tiên của định nghĩa vì chúng không được kế thừa (xem định nghĩa về thừa kế các phương thức trừu tượng trong phần 8.4.8 của JSL). và do đó chúng được yêu cầu mục thứ hai của định nghĩa.
Về cơ bản, lớp học của bạn trừu tượng cho đến khi bạn cung cấp các triển khai cụ thể cho tất cả các phương thức trừu tượng của mình (các phương thức rõ ràng trong lớp của bạn hoặc ẩn từ các lớp cha). Hãy nhớ rằng: "phạm vi gói" là khi bạn * không * chỉ định "công khai" hoặc "được bảo vệ" hoặc "riêng tư"; nó có thể nhìn thấy ở bất cứ nơi nào bên trong gói và không hiển thị bên ngoài gói. – paulsm4