Animal
คลาสพาเรนต์ซึ่งเป็นตัวแทนของสัตว์ และสร้างspeak
เมธอดในนั้น:
public class Animal {
public void speak() {
System.out.println("Hello!");
}
}
แม้ว่าเราจะเพิ่งเริ่มเขียนโปรแกรม แต่คุณอาจเห็นปัญหาที่อาจเกิดขึ้นได้: โลกนี้เต็มไปด้วยสัตว์มากมาย และพวกมันทั้งหมด "พูด" ต่างกัน: แมวเหมียว เป็ดตัวเบ้อเร่อ งูขู่ฟ่อ ฯลฯ เป้าหมายของเรานั้นง่ายมาก: เรา ต้องการหลีกเลี่ยงการสร้างวิธีการพูดมากมาย แทนที่จะสร้างmeow()
วิธีการร้องเหมียวhiss()
ส่งเสียงฟู่ ฯลฯ เราต้องการให้งูส่งเสียงฟู่ แมวร้องเหมียว และสุนัขเห่าเมื่อspeak()
เรียกวิธีการนี้ เราสามารถทำสิ่งนี้ให้สำเร็จได้โดยง่ายโดยใช้วิธีการ overriding วิกิพีเดียอธิบายคำศัพท์ดังต่อไปนี้: การแทนที่เมธอดในการเขียนโปรแกรมเชิงวัตถุเป็นคุณลักษณะทางภาษาที่อนุญาตให้คลาสย่อยหรือคลาสย่อยจัดเตรียมการใช้งานเฉพาะของเมธอดที่จัดเตรียมไว้แล้วโดยหนึ่งในซูเปอร์คลาสหรือคลาสพาเรนต์ ถูกต้องโดยพื้นฐานแล้ว การแทนที่ทำให้คุณสามารถใช้เมธอดของคลาสหลักและเขียนการใช้งานของคุณเองในแต่ละคลาสที่ได้รับมา การใช้งานใหม่ในคลาสลูก "แทนที่" คลาสในพาเรนต์ ลองดูตัวอย่างนี้ว่าเป็นอย่างไร มาสร้างลูกหลานของAnimal
ชั้นเรียนของเรา 4 คน:
public class Bear extends Animal {
@Override
public void speak() {
System.out.println("Growl!");
}
}
public class Cat extends Animal {
@Override
public void speak() {
System.out.println("Meow!");
}
}
public class Dog extends Animal {
@Override
public void speak() {
System.out.println("Woof!");
}
}
public class Snake extends Animal {
@Override
public void speak() {
System.out.println("Hiss!");
}
}
นี่คือเคล็ดลับเล็กๆ น้อยๆ สำหรับอนาคต: หากต้องการแทนที่เมธอดของคลาสพาเรนต์ ให้เข้าไปในโค้ดของคลาสที่ได้รับมาในIntelliJ IDEกดCtrl+Oแล้วเลือกOverride method...จากเมนู ทำความคุ้นเคยกับการใช้ปุ่มลัดตั้งแต่เริ่มต้น พวกเขาจะเร่งการเข้ารหัส! เพื่อให้ได้ลักษณะการทำงานที่ต้องการ เราทำบางสิ่ง:
- ในแต่ละคลาสที่สืบทอดมา เราสร้างเมธอดที่มีชื่อเดียวกับเมธอดในคลาสพาเรนต์
-
เราบอกคอมไพเลอร์ว่าเราไม่ได้ให้ชื่อเมธอดเดียวกับในคลาสพาเรนต์ แต่เราต้องการแทนที่พฤติกรรมของมัน "ข้อความ" นี้ไปยังคอมไพเลอร์จะถูกส่งผ่านคำอธิบายประกอบ@Override
คำอธิบายประกอบ @Override เหนือเมธอดจะบอกคอมไพเลอร์ (รวมถึงโปรแกรมเมอร์อื่นๆ ที่อ่านโค้ดของคุณ) ว่า "อย่ากังวล นี่ไม่ใช่ข้อผิดพลาดหรือการมองข้าม ฉันทราบดีว่ามีเมธอดนี้อยู่แล้ว และฉันต้องการแทนที่เมธอดนี้ . - เราเขียนการนำไปใช้ที่เราต้องการสำหรับแต่ละคลาสที่สืบทอดมา เมื่อ
speak()
เรียกวิธีการนี้ งูควรขู่ หมีควรคำราม และอื่นๆ
public class Main {
public static void main(String[] args) {
Animal animal1 = new Dog();
Animal animal2 = new Cat();
Animal animal3 = new Bear();
Animal animal4 = new Snake();
animal1.speak();
animal2.speak();
animal3.speak();
animal4.speak();
}
}
เอาต์พุตคอนโซล:
Woof!
Meow!
Growl!
Hiss!
เยี่ยมมาก ทุกอย่างทำงานได้ตามปกติ! เราสร้างตัวแปรอ้างอิง 4 ตัวซึ่งมีประเภทเป็นAnimal
คลาสพาเรนต์ และกำหนดออบเจกต์ที่แตกต่างกัน 4 ตัวของคลาสรองลงมา เป็นผลให้แต่ละวัตถุทำงานแตกต่างกัน สำหรับแต่ละคลาสที่ได้รับมา เมธอดที่ถูกแทนที่จะspeak()
แทนที่speak()
เมธอดที่มีอยู่ของAnimal
คลาส (ซึ่งจะแสดง "Speaking: " บนคอนโซล) การแทนที่เมธอดมีข้อจำกัดหลายประการ:
-
เมธอดที่ถูกแทนที่ต้องมีอาร์กิวเมนต์เดียวกันกับเมธอดในคลาสพาเรนต์
หาก
speak
เมธอดของคลาสพาเรนต์รับ aString
เป็นอินพุต ดังนั้นเมธอดที่ถูกแทนที่ในคลาสรองลงมาจะต้องรับ aString
เป็นอินพุต ด้วย มิฉะนั้น คอมไพเลอร์จะสร้างข้อผิดพลาด:public class Animal { public void speak(String s) { System.out.println("Speaking: " + s); } } public class Cat extends Animal { @Override // Error! public void speak() { System.out.println("Meow!"); } }
-
เมธอดที่ถูกแทนที่ต้องมีประเภทการส่งคืนเหมือนกับเมธอดในคลาสพาเรนต์
มิฉะนั้น เราจะได้รับข้อผิดพลาดในการรวบรวม:
public class Animal { public void speak() { System.out.println("Hello!"); } } public class Cat extends Animal { @Override public String speak() { // Error! System.out.println("Meow!"); return "Meow!"; } }
-
ตัวดัดแปลงการเข้าถึงของเมธอดที่ถูกแทนที่จะต้องไม่แตกต่างจากตัวดั้งเดิม:
public class Animal { public void speak() { System.out.println("Hello!"); } } public class Cat extends Animal { @Override private void speak() { // Error! System.out.println("Meow!"); } }
speak()
สำหรับทุกคน แทนที่จะเป็นเมธอดต่างๆ เช่นbark()
, meow()
เป็นต้น
GO TO FULL VERSION