หลายวิธีในการเรียกวิธีการหลักใน php


90

ตอนแรกฉันก็งงว่าทำไมทั้งสองวิธีการเรียกใช้ในตัวสร้างจึงทำงานได้ แต่ตอนนี้ฉันคิดว่าฉันเข้าใจแล้ว คลาสที่ขยายจะสืบทอดเมธอดของพาเรนต์ราวกับว่ามีการประกาศในคลาสเองและเมธอดนั้นมีอยู่ในพาเรนต์ดังนั้นทั้งสองจึงควรใช้งานได้

ตอนนี้ฉันสงสัยว่ามีวิธีที่ต้องการ (เช่นแนวทางปฏิบัติที่ดีที่สุด) ในการเรียกใช้เมธอด (ผ่านparentหรือthis) หรือไม่และสิ่งเหล่านี้เป็นวิธีที่เหมือนกันในการเรียกใช้โค้ดเดียวกันหรือไม่หรือมีข้อแม้เมื่อใช้มากกว่า อื่น ๆ.

ขอโทษนะฉันอาจคิดมากไปเอง

abstract class Animal {

    function get_species() {

        echo "test";

    }

}

class Dog extends Animal {

    function __construct(){

        $this->get_species();
        parent::get_species();

    }

}

$spike = new Dog;

คำตอบ:


120

มีสามสถานการณ์ (ที่ฉันคิดได้) ที่คุณจะเรียกใช้เมธอดในคลาสย่อยโดยที่เมธอดออกจากคลาสพาเรนต์:

  1. เมธอดไม่ได้ถูกเขียนทับโดยคลาสย่อยมีอยู่ในพาเรนต์เท่านั้น

    นี่เป็นเช่นเดียวกับตัวอย่างของคุณและโดยทั่วไปแล้วจะดีกว่าที่จะใช้$this -> get_species(); คุณพูดถูกว่าในกรณีนี้ทั้งสองเหมือนกันอย่างมีประสิทธิภาพ แต่วิธีนี้ได้รับการสืบทอดมาจากคลาสย่อยดังนั้นจึงไม่มีเหตุผลที่จะแยกความแตกต่าง โดยการใช้$thisคุณจะต้องสอดคล้องกันระหว่างวิธีการสืบทอดและวิธีการที่ประกาศในเครื่อง

  2. เมธอดถูกเขียนทับโดยคลาสย่อยและมีตรรกะที่ไม่ซ้ำกันโดยสิ้นเชิงจากพาเรนต์

    ในกรณีนี้เห็นได้ชัดว่าคุณต้องการใช้$this -> get_species();เนื่องจากคุณไม่ต้องการให้เมธอดเวอร์ชันของผู้ปกครองดำเนินการ อีกครั้งโดยใช้อย่างสม่ำเสมอ$thisคุณไม่จำเป็นต้องกังวลเกี่ยวกับความแตกต่างระหว่างกรณีนี้กับกรณีแรก

  3. เมธอดขยายคลาสพาเรนต์โดยเพิ่มสิ่งที่เมธอดพาเรนต์บรรลุ

    ในกรณีนี้คุณยังคงต้องการใช้`$this -> get_species();เมื่อเรียกใช้เมธอดจากเมธอดอื่นของคลาสย่อย ที่เดียวที่คุณจะเรียกว่าเมธอดหลักจะมาจากเมธอดที่เขียนทับเมธอดหลัก ตัวอย่าง:

    abstract class Animal {
    
        function get_species() {
    
            echo "I am an animal.";
    
        }
    
     }
    
     class Dog extends Animal {
    
         function __construct(){
    
             $this->get_species();
         }
    
         function get_species(){
    
             parent::get_species();
             echo "More specifically, I am a dog.";
         }
    }
    

สถานการณ์เดียวที่ฉันสามารถจินตนาการได้ว่าคุณจะต้องเรียกใช้เมธอดผู้ปกครองโดยตรงนอกวิธีการลบล้างคือถ้าพวกเขาทำสองสิ่งที่แตกต่างกันและคุณรู้ว่าคุณต้องการเมธอดเวอร์ชันของผู้ปกครองไม่ใช่เฉพาะในพื้นที่ ไม่ควรเป็นเช่นนั้น แต่ถ้ามันปรากฏตัววิธีที่สะอาดในการเข้าถึงสิ่งนี้คือการสร้างเมธอดใหม่ที่มีชื่อเหมือนกับget_parentSpecies()ที่เรียกว่าเมธอดหลัก:

function get_parentSpecies(){

     parent::get_species();
}

อีกครั้งสิ่งนี้ช่วยให้ทุกอย่างดีและสอดคล้องกันโดยอนุญาตให้มีการเปลี่ยนแปลง / แก้ไขวิธีการเฉพาะที่แทนที่จะอาศัยวิธีการหลัก


ฉันจะทำอย่างไรโดยไม่ต้อง "ขยาย" เหมือนฉันมี "ขา" ในคลาส "มนุษย์" แต่ฉันไม่จำเป็นต้องขยายมันเพราะฉันไม่ต้องการฟังก์ชัน "มนุษย์" ของผู้ปกครอง ตอนนี้ถ้าฉันสร้าง$leg = new leg()ภายในhumanฉันจะเรียกฟังก์ชันของมนุษย์จากภายในอินสแตนซ์ขาได้$legอย่างไร
user151496

@ user151496 ขาไม่ใช่คลาสย่อยของมนุษย์ มนุษย์มีขาหลายขา แต่ขาไม่ใช่ประเภทของมนุษย์ ดังนั้นคุณไม่ควรมีชั้นของขาที่สืบทอดมาจากมนุษย์เพราะขาไม่ใช่มนุษย์
Beetle

คุณจะทำให้ Leg เป็นคลาสที่มีอินเทอร์เฟซของ Leggy หรือไม่? หรือแค่ให้คลาส Human ใช้ Leggy? เราจะนิยามได้อย่างไรว่าขานั้นไม่ได้มีไว้สำหรับมนุษย์เท่านั้น แต่ยังรวมถึงขาของมนุษย์ที่มีลักษณะเฉพาะของมนุษย์และเป็นสมบัติทั่วไปของมนุษย์ด้วย
Anthony

2
paamayim nekudotayim ค่อนข้างสับสน แวบแรกดูเหมือนว่าคุณกำลังเรียกใช้วิธีการแบบคงที่ ควรเป็น parent-> get_species () แทน
peterchaula

เห็นด้วย การโทรแบบคงที่ทำให้เกิดความสับสนในหลาย ๆ ด้าน ฉันควรอัปเดตสิ่งนี้ในบางจุด
Anthony

5

ถ้าฉันไม่เข้าใจคำถามฉันมักจะใช้ $ this-> get_species เพราะคลาสย่อย (ในกรณีนี้คือสุนัข) สามารถเขียนทับเมธอดนั้นได้เนื่องจากมันขยายออกไป หากสุนัขคลาสไม่ได้กำหนดวิธีการใหม่ทั้งสองวิธีจะเทียบเท่ากันในการทำงาน แต่ถ้าในอนาคตคุณตัดสินใจว่าคุณต้องการให้เมธอด get_species ใน dog ควรพิมพ์ "dog" จากนั้นคุณจะต้องย้อนกลับไปดูโค้ดทั้งหมดและ เปลี่ยนมัน

เมื่อคุณใช้ $ สิ่งนี้เป็นส่วนหนึ่งของออบเจ็กต์ที่คุณสร้างขึ้นและจะเป็นข้อมูลล่าสุดเสมอเช่นกัน (หากคุณสมบัติที่ใช้มีการเปลี่ยนแปลงอย่างใดอย่างหนึ่งในอายุการใช้งานของวัตถุ) ในขณะที่ใช้คลาสหลัก กำลังเรียกใช้เมธอดคลาสแบบคงที่


นั่นเป็นจุดที่ดีเกี่ยวกับการใช้ $ นี้ในกรณีที่ฉันต้องการแทนที่เมธอด ขอบคุณ
jerry
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.