JavaRush /จาวาบล็อก /Random-TH /กลไกการแทนที่เมธอดหรือแทนที่ใน Java

กลไกการแทนที่เมธอดหรือแทนที่ใน Java

เผยแพร่ในกลุ่ม
สวัสดี! คุณใช้วิธีการใน Java อยู่แล้วและรู้เรื่องเกี่ยวกับมันมากมาย คุณอาจพบสถานการณ์ที่มีหลายวิธีในคลาสเดียวที่มีชื่อเดียวกัน แต่มีอาร์กิวเมนต์ต่างกัน หากคุณจำได้ ในกรณีเหล่านั้น เราใช้กลไกการโอเวอร์โหลดของวิธีการ วันนี้เรามาดูสถานการณ์ที่แตกต่างกัน ลองนึกภาพว่าเรามีวิธีการทั่วไปวิธีหนึ่ง แต่มันควรทำสิ่งต่าง ๆ ขึ้นอยู่กับคลาสที่ถูกเรียกใช้ จะนำพฤติกรรมนี้ไปใช้อย่างไร? หากต้องการทราบ เรามาเรียนชั้นเรียนผู้ปกครองAnimalที่แสดงถึงสัตว์และสร้างวิธีการในนั้นvoice- " เสียง ":
public class Animal {

   public void voice() {

       System.out.println("Voice!");
   }
}
แม้ว่าเราจะเพิ่งเริ่มเขียนโปรแกรม แต่คุณก็น่าจะมองเห็นปัญหาที่อาจเกิดขึ้นได้: มีสัตว์มากมายในโลกนี้ และพวกมันต่างก็ "พูด" ต่างกัน: แมวร้องเหมียว เป็ดต้มตุ๋น งูส่งเสียงฟู่ กลไกการเอาชนะวิธีการทำงานอย่างไร - 2 เป้าหมายของเรานั้นง่ายมาก: หลีกเลี่ยงการสร้างวิธีการลงคะแนนเสียงมากมาย แทนที่จะสร้างวิธี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... ” จากเมนู ทำความคุ้นเคยกับการใช้ปุ่มลัดตั้งแต่เริ่มต้นจะช่วยให้การเขียนโปรแกรมเร็วขึ้น! เพื่อกำหนดลักษณะการทำงานที่เราต้องการ เราได้ทำบางสิ่ง:
  1. เราสร้างวิธีการในแต่ละคลาสสืบทอดที่มีชื่อเดียวกันกับวิธีการในคลาสหลัก
  2. เราบอกคอมไพลเลอร์ว่าเราตั้งชื่อวิธีการเหมือนกับในคลาสพาเรนต์ด้วยเหตุผล: เราต้องการแทนที่พฤติกรรมของมัน สำหรับ “ข้อความ” นี้ที่ส่งถึงคอมไพลเลอร์ เราได้ใส่คำอธิบายประกอบ @Overrideไว้ บนเมธอด
    คำอธิบายประกอบ @Override ที่วางอยู่เหนือเมธอดจะบอกคอมไพเลอร์ (และโปรแกรมเมอร์ก็อ่านโค้ดของคุณด้วย): “ทุกอย่างโอเค นี่ไม่ใช่ความผิดพลาดหรือการหลงลืมของฉัน ฉันจำได้ว่ามีวิธีดังกล่าวอยู่แล้ว และฉันต้องการแทนที่มัน"

  3. เราเขียนการใช้งานที่เราต้องการสำหรับคลาสสืบทอดแต่ละคลาส เมื่อถูกเรียก งู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!" ไปยังคอนโซล) กลไกการเอาชนะวิธีการทำงานอย่างไร - 3 การเอาชนะมีข้อจำกัดหลายประการ:
  1. วิธีการแทนที่จะต้องมีอาร์กิวเมนต์เดียวกันกับวิธีการหลัก

    ถ้าเมธอด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!");
       }
    }

  2. วิธีการแทนที่จะต้องมีประเภทการส่งคืนเช่นเดียวกับวิธีการหลัก

    มิฉะนั้นเราจะได้รับข้อผิดพลาดในการรวบรวม:

    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!";
       }
    }

  3. ตัวแก้ไขการเข้าถึงของวิธีการแทนที่ก็ไม่สามารถแตกต่างจากวิธี "ดั้งเดิม" ได้:

    public class Animal {
    
       public void voice() {
    
           System.out.println("Voice!");
       }
    }
    
    public class Cat extends Animal {
    
       @Override
       private void voice() {      //error!
           System.out.println("Meow!");
       }
    }
การแทนที่เมธอดใน Javaเป็นหนึ่งในเครื่องมือในการนำแนวคิดเรื่องความหลากหลายไปใช้ (หลักการของ OOP ที่เราพูดถึงในการบรรยายครั้งล่าสุด) ดังนั้นข้อได้เปรียบหลักของการใช้งานก็คือความยืดหยุ่นแบบเดียวกับที่เราพูดถึงก่อนหน้านี้ เราสามารถสร้างระบบคลาสที่เรียบง่ายและลอจิคัล ซึ่งแต่ละคลาสจะมีพฤติกรรมเฉพาะ (สุนัขเห่า แมวเหมียว) แต่มีอินเทอร์เฟซเดียว - วิธีการเดียวสำหรับ voice()ทั้งหมด แทนที่จะเป็นวิธีการมากมายvoiceDog()ฯลฯvoiceCat()
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION