Java - การลบล้าง
ในบทที่แล้วเราได้พูดถึง superclasses และ subclasses หากคลาสสืบทอดเมธอดจากซูเปอร์คลาสมีโอกาสที่จะลบล้างเมธอดหากไม่ถูกทำเครื่องหมายเป็นขั้นสุดท้าย
ประโยชน์ของการลบล้างคือ: ความสามารถในการกำหนดลักษณะการทำงานที่เฉพาะเจาะจงสำหรับประเภทซับคลาสซึ่งหมายความว่าคลาสย่อยสามารถใช้เมธอดคลาสพาเรนต์ตามความต้องการได้
ในแง่เชิงวัตถุการแทนที่หมายถึงการแทนที่ฟังก์ชันการทำงานของวิธีการที่มีอยู่
ตัวอย่าง
ให้เราดูตัวอย่าง
class Animal {
public void move() {
System.out.println("Animals can move");
}
}
class Dog extends Animal {
public void move() {
System.out.println("Dogs can walk and run");
}
}
public class TestDog {
public static void main(String args[]) {
Animal a = new Animal(); // Animal reference and object
Animal b = new Dog(); // Animal reference but Dog object
a.move(); // runs the method in Animal class
b.move(); // runs the method in Dog class
}
}
สิ่งนี้จะให้ผลลัพธ์ดังต่อไปนี้ -
เอาต์พุต
Animals can move
Dogs can walk and run
ในตัวอย่างข้างต้นคุณจะเห็นว่าแม้ว่า bเป็นสัตว์ประเภทหนึ่งที่ใช้วิธีการย้ายในคลาส Dog เหตุผลคือ: ในเวลาคอมไพล์การตรวจสอบจะทำในประเภทการอ้างอิง อย่างไรก็ตามในรันไทม์ JVM จะระบุประเภทอ็อบเจ็กต์และจะรันเมธอดที่เป็นของอ็อบเจ็กต์นั้น
ดังนั้นในตัวอย่างข้างต้นโปรแกรมจะคอมไพล์อย่างถูกต้องเนื่องจากคลาส Animal มีการย้ายเมธอด จากนั้นที่รันไทม์จะรันเมธอดเฉพาะสำหรับอ็อบเจ็กต์นั้น
ลองพิจารณาตัวอย่างต่อไปนี้ -
ตัวอย่าง
class Animal {
public void move() {
System.out.println("Animals can move");
}
}
class Dog extends Animal {
public void move() {
System.out.println("Dogs can walk and run");
}
public void bark() {
System.out.println("Dogs can bark");
}
}
public class TestDog {
public static void main(String args[]) {
Animal a = new Animal(); // Animal reference and object
Animal b = new Dog(); // Animal reference but Dog object
a.move(); // runs the method in Animal class
b.move(); // runs the method in Dog class
b.bark();
}
}
สิ่งนี้จะให้ผลลัพธ์ดังต่อไปนี้ -
เอาต์พุต
TestDog.java:26: error: cannot find symbol
b.bark();
^
symbol: method bark()
location: variable b of type Animal
1 error
โปรแกรมนี้จะแสดงข้อผิดพลาดเวลาคอมไพล์เนื่องจากประเภทการอ้างอิงของ b Animal ไม่มีเมธอดตามชื่อของ bark
กฎสำหรับการแทนที่วิธีการ
รายการอาร์กิวเมนต์ควรเหมือนกับของเมธอดที่ถูกลบล้าง
ประเภทการส่งคืนควรเหมือนกันหรือเป็นประเภทย่อยของประเภทการส่งคืนที่ประกาศในเมธอดเดิมที่ถูกแทนที่ในซูเปอร์คลาส
ระดับการเข้าถึงต้องไม่ จำกัด มากกว่าระดับการเข้าถึงของวิธีการที่ถูกลบล้าง ตัวอย่างเช่น: หากวิธีการ superclass ถูกประกาศแบบสาธารณะวิธีการเขียนทับในคลาสย่อยจะไม่สามารถเป็นแบบส่วนตัวหรือได้รับการป้องกัน
เมธอดอินสแตนซ์สามารถถูกแทนที่ได้ก็ต่อเมื่อมีการสืบทอดโดยคลาสย่อยเท่านั้น
ไม่สามารถแทนที่เมธอดที่ประกาศขั้นสุดท้ายได้
เมธอดที่ประกาศแบบคงที่ไม่สามารถแทนที่ได้ แต่สามารถประกาศใหม่ได้
หากไม่สามารถสืบทอดเมธอดได้ก็จะไม่สามารถลบล้างได้
คลาสย่อยภายในแพ็กเกจเดียวกับซูเปอร์คลาสของอินสแตนซ์สามารถแทนที่เมธอด superclass ใด ๆ ที่ไม่ได้ประกาศว่าเป็นไพรเวตหรือขั้นสุดท้าย
คลาสย่อยในแพ็กเกจอื่นสามารถลบล้างเมธอดที่ไม่ใช่ขั้นสุดท้ายที่ประกาศต่อสาธารณะหรือได้รับการป้องกันเท่านั้น
วิธีการลบล้างอาจทำให้เกิดข้อยกเว้นที่ไม่เลือกได้ไม่ว่าเมธอดที่ลบล้างจะส่งข้อยกเว้นหรือไม่ก็ตาม อย่างไรก็ตามวิธีการลบล้างไม่ควรทิ้งข้อยกเว้นที่ตรวจสอบแล้วซึ่งใหม่หรือกว้างกว่าวิธีที่ประกาศโดยวิธีการลบล้าง วิธีการลบล้างอาจทำให้เกิดข้อยกเว้นที่แคบกว่าหรือน้อยกว่าวิธีการลบล้าง
ไม่สามารถลบล้างตัวสร้างได้
การใช้ super Keyword
เมื่อเรียกใช้เมธอดที่ถูกแทนที่รุ่น superclass super ใช้คำหลัก
ตัวอย่าง
class Animal {
public void move() {
System.out.println("Animals can move");
}
}
class Dog extends Animal {
public void move() {
super.move(); // invokes the super class method
System.out.println("Dogs can walk and run");
}
}
public class TestDog {
public static void main(String args[]) {
Animal b = new Dog(); // Animal reference but Dog object
b.move(); // runs the method in Dog class
}
}
สิ่งนี้จะให้ผลลัพธ์ดังต่อไปนี้ -
เอาต์พุต
Animals can move
Dogs can walk and run