php - Comment passer outre la fonction de caractère et l'appeler de la fonction surchargée?


Scénario:

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

Ce code ne fonctionne pas, et je ne peux pas trouver un moyen d'appeler une fonction trait comme si elle avait été héritée. J'ai essayé d'appeler self::calc($v) , static::calc($v) , parent::calc($v) , A::calc($v) et ce qui suit:

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

class MyClass {
    use A {
        calc as traitcalc;
    }

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

Rien ne fonctionne.

Y at-il un moyen de le faire fonctionner ou dois-je remplacer complètement la fonction de trait qui est beaucoup plus complexe que cela :)



Answers



Votre dernier était presque là:

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

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

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

Le trait n'est pas une classe. Vous ne pouvez pas accéder à ses membres directement. Il s'agit essentiellement de copier et coller automatisé ...




Si la classe implémente la méthode directement, elle n'utilisera pas la version des traits. Peut-être que vous pensez à:

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

Comme les classes enfants n'implémentent pas la méthode directement, elles utiliseront d'abord celle du trait si elles utilisent autrement celle de la classe parente.

Si vous le souhaitez, le trait peut utiliser la méthode dans la classe parent (en supposant que vous sachiez que la méthode serait là), par exemple

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)

Vous pouvez également fournir des moyens de remplacer, mais toujours accéder à la méthode trait comme suit:

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

Vous pouvez le voir sur http://sandbox.onlinephpfunctions.com/code/e53f6e8f9834aea5e038aec4766ac7e1c19cc2b5




Une approche alternative si vous êtes intéressé - avec une classe intermédiaire supplémentaire pour utiliser la voie normale OOO. Cela simplifie l'utilisation avec 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);
    }
}



En utilisant un autre trait:

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