เมื่อออกแบบคลาสที่มีไว้สำหรับการสืบทอด (เช่น คลาสนามธรรม) ถือเป็นแนวปฏิบัติที่ดีที่จะไม่ใช้งานอินเทอร์เฟซ
Serializable
และต้องตัดสินใจเป็นรายบุคคลในแต่ละคลาสสืบทอดว่าจำเป็นต้องทำให้เป็นอนุกรมหรือไม่ อย่างไรก็ตาม คลาสดังกล่าวต้องมีคอนสตรัคเตอร์เริ่มต้นเพื่อให้กลไกการทำให้ซีเรียลไลซ์สร้างอ็อบเจ็กต์ได้อย่างถูกต้อง และบางครั้งก็ไม่มีวิธีใดที่จะจัดเตรียมคอนสตรัคเตอร์เริ่มต้นโดยไม่ทำลายความสมบูรณ์ของคลาส คลาสดังกล่าวมักจะต้องใช้เป็นพารามิเตอร์ของอ็อบเจ็กต์บางตัวโดยที่ไม่สามารถทำงานได้ตามปกติ และการจัดเตรียมคอนสตรัคเตอร์เริ่มต้นจะละเมิดความสมบูรณ์ของคลาส ในสถานการณ์เช่นนี้ คุณสามารถจัดเตรียมตัวสร้างได้ แต่ห้ามไม่ให้ใช้งานตัวสร้างนั้นจนกว่าจะเริ่มต้นใช้งานโดยสมบูรณ์ ในการดำเนินการนี้ คุณสามารถแนะนำสถานะลงในคลาสได้ และอนุญาตให้เรียกใช้เมธอดได้ก็ต่อเมื่อสถานะของคลาสนี้ "เริ่มต้น" เท่านั้น ตัวอย่างจากหนังสือ"Effective java" :
public abstract class AbstractFoo {
private int x, y;
private enum State {
NEW, INITIALIZING, INITIALIZED
};
private final AtomicReference<State> init = new AtomicReference<State>(State.NEW);
protected AbstractFoo() {}
public AbstractFoo(int x, int y) {
initialize(x, y);
}
protected final void initialize(int x, int y) {
if (!init.compareAndSet(State.NEW, State.INITIALIZING)) {
throw new IllegalStateException("Already initialized");
}
this.x = x;
this.y = y;
init.set(State.INITIALIZED);
}
protected final int getX() {
checkInit();
return x;
}
protected final int getY() {
checkInit();
return y;
}
private void checkInit() {
if (init.get() != State.INITIALIZED) {
throw new IllegalStateException("Uninitialized");
}
}
}
class Foo extends AbstractFoo implements Serializable {
private void readObject(ObjectInputStream s) throws IOException,
ClassNotFoundException {
s.defaultReadObject();
int x = s.readInt();
int y = s.readInt();
initialize(x, y);
}
private void writeObject(ObjectOutputStream s) throws IOException {
s.defaultWriteObject();
s.writeInt(getX());
s.writeInt(getY());
}
public Foo(int x, int y) {
super(x, y);
}
}
ในเวลาเดียวกัน วิธีการทั้งหมดของคลาสนี้จะต้องตรวจสอบสถานะปัจจุบันของคลาสและ ป้องกัน การใช้งานที่ไม่ถูกต้อง และวิธีการreadObject()
และ จะต้องกำหนดไว้ในคลาสลูกหลาน writeObject()
ลิงก์ไปยังแหล่งที่มาดั้งเดิม: http://0agr.ru
GO TO FULL VERSION