Sobes.tech
Middle

Co dělat, pokud mají dva traits metodu se stejným názvem?

sobes.tech AI

Odpověď od AI

Když dojde ke kolizi názvů metod v traitech, existuje několik možností řešení:

  1. Operátor předpony insteadof: Umožňuje vybrat metodu z určitého traitu, která bude použita, ignorujíc stejnou metodu z jiného traitu.

    <?php
    trait TraitA {
        public function doSomething() {
            echo "Z TraitA";
        }
    }
    
    trait TraitB {
        public function doSomething() {
            echo "Z TraitB";
        }
    }
    
    class MyClass {
        use TraitA, TraitB {
            TraitA::doSomething insteadof TraitB; // Používáme metodu z TraitA
        }
    }
    
    $obj = new MyClass();
    $obj->doSomething(); // Vypíše "Z TraitA"
    

    Lze specifikovat více výjimek:

    <?php
    trait TraitA {
        public function methodA() { echo "A_a"; }
        public function methodB() { echo "A_b"; }
    }
    
    trait TraitB {
        public function methodA() { echo "B_a"; }
        public function methodB() { echo "B_b"; }
    }
    
    class MyClass {
        use TraitA, TraitB {
            TraitA::methodA insteadof TraitB;
            TraitB::methodB insteadof TraitA;
        }
    }
    
  2. Operátor předpony as: Umožňuje přejmenovat jednu z konfliktních metod.

    <?php
    trait TraitA {
        public function doSomething() {
            echo "Z TraitA";
        }
    }
    
    trait TraitB {
        public function doSomething() {
            echo "Z TraitB";
        }
    }
    
    class MyClass {
        use TraitA, TraitB {
            TraitB::doSomething as doSomethingFromB; // Přejmenováváme metodu z TraitB
        }
    
        public function callBoth() {
            $this->doSomething();        // Zavolá metodu z TraitA
            $this->doSomethingFromB(); // Zavolá přejmenovanou metodu z TraitB
        }
    }
    
    $obj = new MyClass();
    $obj->callBoth(); // Vypíše "Z TraitAZ TraitB"
    

    Operátor as lze použít ve spojení s insteadof a umožňuje změnit viditelnost metody.

    <?php
    trait TraitA {
        private function internalMethod() {
            echo "Privátní z TraitA";
        }
    }
    
    class MyClass {
        use TraitA {
            internalMethod as public externalMethod; // Přejmenováváme a zpřístupňujeme
        }
    }
    
    $obj = new MyClass();
    $obj->externalMethod(); // Vypíše "Privátní z TraitA"
    
  3. Explicitní definice metody v třídě: Pokud třída, která používá trait, explicitně definuje metodu se stejným názvem, má přednost tato metoda třídy před metodami traitů.

    <?php
    trait TraitA {
        public function doSomething() {
            echo "Z TraitA";
        }
    }
    
    trait TraitB {
        public function doSomething() {
            echo "Z TraitB";
        }
    }
    
    class MyClass {
        use TraitA, TraitB;
    
        public function doSomething() { // Třída definuje vlastní metodu
            echo "Z MyClass";
        }
    }
    
    $obj = new MyClass();
    $obj->doSomething(); // Vypíše "Z MyClass"
    

Bez explicitního řešení kolize pomocí insteadof nebo as, nebo přepsáním metody v třídě, PHP při pokusu o použití třídy s konfliktními metodami traitů vypíše chybu E_STRICT.