Animal
ที่แสดงถึงสัตว์และสร้างวิธีการในนั้นvoice
- " เสียง ":
public class Animal {
public void voice() {
System.out.println("Voice!");
}
}
แม้ว่าเราจะเพิ่งเริ่มเขียนโปรแกรม แต่คุณก็น่าจะมองเห็นปัญหาที่อาจเกิดขึ้นได้: มีสัตว์มากมายในโลกนี้ และพวกมันต่างก็ "พูด" ต่างกัน: แมวร้องเหมียว เป็ดต้มตุ๋น งูส่งเสียงฟู่ 
voiceCat()
การร้องเหมียวvoiceSnake()
เสียงฟู่ ฯลฯ เราต้องการให้voice()
งูส่งเสียงขู่ แมวร้องเหมียว และสุนัขเห่าเมื่อมีการเรียกวิธีนี้ เราสามารถบรรลุสิ่งนี้ได้อย่างง่ายดายโดยใช้กลไกการแทนที่วิธีการ (แทนที่ใน Java ) วิกิพีเดียให้คำอธิบายต่อไปนี้ของคำว่า "การเอาชนะ": การแทนที่เมธอดใน การเขียนโปรแกรม เชิงวัตถุเป็นหนึ่งในคุณลักษณะของภาษาการเขียนโปรแกรมที่อนุญาตให้คลาสย่อยหรือคลาสลูกจัดเตรียมการดำเนินการเฉพาะของวิธีการที่ถูกนำไปใช้แล้วในซูเปอร์คลาสตัวใดตัวหนึ่ง หรือชั้นเรียนผู้ปกครอง โดยทั่วไปแล้วมันก็ถูกต้อง การเอาชนะช่วยให้คุณสามารถใช้เมธอดของคลาสพาเรนต์และเขียนการใช้งานเมธอดนี้ของคุณเองในแต่ละคลาสสืบทอด การใช้งานใหม่จะ "แทนที่" พาเรนต์ในคลาสลูก เรามาดูกันว่าสิ่งนี้มีลักษณะอย่างไรพร้อมตัวอย่าง มาสร้างคลาสสืบทอด 4 คลาสสำหรับคลาสของเราAnimal
:
public class Bear extends Animal {
@Override
public void voice() {
System.out.println("Р-р-р!");
}
}
public class Cat extends Animal {
@Override
public void voice() {
System.out.println("Meow!");
}
}
public class Dog extends Animal {
@Override
public void voice() {
System.out.println("Woof!");
}
}
public class Snake extends Animal {
@Override
public void voice() {
System.out.println("Ш-ш-ш!");
}
}
เคล็ดลับเล็กๆ น้อยๆ สำหรับอนาคต: หากต้องการแทนที่เมธอดของคลาสพาเรนต์ ให้ไปที่โค้ดของคลาสที่สืบทอดในIntellij IDE a กดCtrl+Oแล้วเลือก “ Override method... ” จากเมนู ทำความคุ้นเคยกับการใช้ปุ่มลัดตั้งแต่เริ่มต้นจะช่วยให้การเขียนโปรแกรมเร็วขึ้น! เพื่อกำหนดลักษณะการทำงานที่เราต้องการ เราได้ทำบางสิ่ง:
- เราสร้างวิธีการในแต่ละคลาสสืบทอดที่มีชื่อเดียวกันกับวิธีการในคลาสหลัก
-
เราบอกคอมไพลเลอร์ว่าเราตั้งชื่อวิธีการเหมือนกับในคลาสพาเรนต์ด้วยเหตุผล: เราต้องการแทนที่พฤติกรรมของมัน สำหรับ “ข้อความ” นี้ที่ส่งถึงคอมไพลเลอร์ เราได้ใส่คำอธิบายประกอบ @Overrideไว้ บนเมธอด
คำอธิบายประกอบ @Override ที่วางอยู่เหนือเมธอดจะบอกคอมไพเลอร์ (และโปรแกรมเมอร์ก็อ่านโค้ดของคุณด้วย): “ทุกอย่างโอเค นี่ไม่ใช่ความผิดพลาดหรือการหลงลืมของฉัน ฉันจำได้ว่ามีวิธีดังกล่าวอยู่แล้ว และฉันต้องการแทนที่มัน" - เราเขียนการใช้งานที่เราต้องการสำหรับคลาสสืบทอดแต่ละคลาส เมื่อถูกเรียก งู
voice()
ก็ส่งเสียงขู่ หมีก็คำราม ฯลฯ
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.voice();
animal2.voice();
animal3.voice();
animal4.voice();
}
}
เอาต์พุตคอนโซล: Woof! เหมียว! อร๊าย! จุ๊ๆ! เยี่ยมมาก ทุกอย่างทำงานได้ตามปกติ! เราสร้างตัวแปรอ้างอิง 4 ตัวของคลาสพาเรนต์Animal
และกำหนดให้กับอ็อบเจ็กต์ที่แตกต่างกัน 4 ตัวของคลาสลูกหลาน เป็นผลให้แต่ละวัตถุมีพฤติกรรมที่แตกต่างกัน สำหรับแต่ละคลาสที่สืบทอด วิธีการแทนที่จะvoice()
แทนที่วิธี "ดั้งเดิม" voice()
จากคลาสAnimal
(ซึ่งเพียงแค่ส่งสัญญาณ "Voice!" ไปยังคอนโซล) 
-
วิธีการแทนที่จะต้องมีอาร์กิวเมนต์เดียวกันกับวิธีการหลัก
ถ้าเมธอด
voice
ในคลาสพาเรนต์ยอมรับเป็นอินพุตString
เมธอดที่ถูกแทนที่ในคลาสลูกจะต้องยอมรับเป็นอินพุตด้วยString
มิฉะนั้นคอมไพเลอร์จะโยนข้อผิดพลาด:public class Animal { public void voice(String s) { System.out.println("Voice! " + s); } } public class Cat extends Animal { @Override//error! public void voice() { System.out.println("Meow!"); } }
-
วิธีการแทนที่จะต้องมีประเภทการส่งคืนเช่นเดียวกับวิธีการหลัก
มิฉะนั้นเราจะได้รับข้อผิดพลาดในการรวบรวม:
public class Animal { public void voice() { System.out.println("Voice!"); } } public class Cat extends Animal { @Override public String voice() { //error! System.out.println("Meow!"); return "Meow!"; } }
-
ตัวแก้ไขการเข้าถึงของวิธีการแทนที่ก็ไม่สามารถแตกต่างจากวิธี "ดั้งเดิม" ได้:
public class Animal { public void voice() { System.out.println("Voice!"); } } public class Cat extends Animal { @Override private void voice() { //error! System.out.println("Meow!"); } }
voice()
ทั้งหมด แทนที่จะเป็นวิธีการมากมายvoiceDog()
ฯลฯvoiceCat()
GO TO FULL VERSION