php - Wie überschreibe ich die Merkmalsfunktion und rufe sie von der überschriebenen Funktion auf?


Szenario:

trait A {
    function calc($v) {
        return $v+1;
    }
}

class MyClass {
    use A;

    function calc($v) {
        $v++;
        return A::calc($v);
    }
}

print (new MyClass())->calc(2); // should print 4

Dieser Code funktioniert nicht und ich kann keine Möglichkeit finden, eine Merkmalsfunktion wie vererbt aufzurufen. Ich versuchte, self::calc($v) , static::calc($v) , parent::calc($v) , A::calc($v) und das folgende zu A::calc($v) :

trait A {
    function calc($v) {
        return $v+1;
    }
}

class MyClass {
    use A {
        calc as traitcalc;
    }

    function calc($v) {
        $v++;
        return traitcalc($v);
    }
}

Nichts funktioniert.

Gibt es eine Möglichkeit, es zum Laufen zu bringen, oder muss ich die Merkmalsfunktion vollständig übergehen, die viel komplexer ist als diese :)



Answers



Dein letzter war fast da:

trait A {
    function calc($v) {
        return $v+1;
    }
}

class MyClass {
    use A {
        calc as protected traitcalc;
    }

    function calc($v) {
        $v++;
        return $this->traitcalc($v);
    }
}

Das Merkmal ist keine Klasse. Sie können nicht direkt auf ihre Mitglieder zugreifen. Es ist im Grunde nur automatisiertes Kopieren und Einfügen ...




Wenn die Klasse die Methode direkt implementiert, wird sie nicht die Merkmalsversion verwenden. Vielleicht denken Sie an Folgendes:

trait A {
    function calc($v) {
        return $v+1;
    }
}

class MyClass {
    function calc($v) {
        return $v+2;
    }
}

class MyChildClass extends MyClass{
}

class MyTraitChildClass extends MyClass{
    use A;
}

print (new MyChildClass())->calc(2); // will print 4

print (new MyTraitChildClass())->calc(2); // will print 3

Da die untergeordneten Klassen die Methode nicht direkt implementieren, verwenden sie zuerst die der Eigenschaft, wenn sie die der übergeordneten Klasse anderweitig verwenden.

Wenn Sie möchten, kann die Eigenschaft Methode in der Elternklasse verwenden (vorausgesetzt, Sie wissen, dass die Methode dort wäre), z.

trait A {
    function calc($v) {
        return parent::calc($v*3);
    }
}
// .... other code from above
print (new MyTraitChildClass())->calc(2); // will print 8 (2*3 + 2)

Sie können auch Möglichkeiten zum Außerkraftsetzen bereitstellen, aber dennoch wie folgt auf die Merkmalsmethode zugreifen:

trait A {
    function trait_calc($v) {
        return $v*3;
    }
}

class MyClass {
    function calc($v) {
        return $v+2;
    }
}


class MyTraitChildClass extends MyClass{
    use A {
      A::trait_calc as calc;
    }
}


class MySecondTraitChildClass extends MyClass{
    use A {
      A::trait_calc as calc;
    }

    public function calc($v) {
      return $this->trait_calc($v)+.5;
    }
}


print (new MyTraitChildClass())->calc(2); // will print 6
echo "\n";
print (new MySecondTraitChildClass())->calc(2); // will print 6.5

Sie können es unter http://sandbox.onlinephpfunctions.com/code/e53f6e8f9834aea5e038aec4766ac7e1c19cc2b5 sehen.




Ein alternativer Ansatz bei Interesse - mit einer zusätzlichen Zwischenklasse, um die normale OOO-Methode zu verwenden. Dies vereinfacht die Verwendung mit parent :: methodname

trait A {
    function calc($v) {
        return $v+1;
    }
}

// an intermediate class that just uses the trait
class IntClass {
    use A;
}

// an extended class from IntClass
class MyClass extends IntClass {
    function calc($v) {
        $v++;
        return parent::calc($v);
    }
}



Ein anderes Merkmal verwenden:

trait ATrait {
    function calc($v) {
        return $v+1;
    }
}

class A {
    use ATrait;
}

trait BTrait {
    function calc($v) {
        $v++;
        return parent::calc($v);
    }
}

class B extends A {
    use BTrait;
}

print (new B())->calc(2); // should print 4