61 votes

Chaîner des méthodes statiques en PHP ?

Est-il possible d'enchaîner des méthodes statiques à l'aide d'une classe statique ? Imaginons que je veuille faire quelque chose comme ceci :

$value = TestClass::toValue(5)::add(3)::subtract(2)::add(8)::result();

. . et je voudrais évidemment que le nombre 14 soit attribué à $value. Cela est-il possible ?

Mise à jour : Cela ne fonctionne pas (vous ne pouvez pas retourner "self" - ce n'est pas une instance !), mais c'est là où mes pensées m'ont mené :

class TestClass {
    public static $currentValue;

    public static function toValue($value) {
        self::$currentValue = $value;
    }

    public static function add($value) {
        self::$currentValue = self::$currentValue + $value;
        return self;
    }

    public static function subtract($value) {
        self::$currentValue = self::$currentValue - $value;
        return self;
    }

    public static function result() {
        return self::$value;
    }
}

Après avoir résolu ce problème, je pense qu'il serait plus logique de travailler simplement avec une instance de classe plutôt que d'essayer d'enchaîner les appels de fonctions statiques (ce qui ne semble pas possible, à moins que l'exemple ci-dessus puisse être modifié d'une manière ou d'une autre).

55voto

Mathew Byrne Points 1083

J'aime la solution proposée par Camilo ci-dessus, essentiellement parce que tout ce que vous faites est de modifier la valeur d'un membre statique, et parce que vous voulez le chaînage (même si ce n'est que du sucre syntaxique), alors l'instanciation de TestClass est probablement la meilleure solution.

Je suggérerais un modèle Singleton si vous voulez restreindre l'instanciation de la classe :

class TestClass
{   
    public static $currentValue;

    private static $_instance = null;

    private function __construct () { }

    public static function getInstance ()
    {
        if (self::$_instance === null) {
            self::$_instance = new self;
        }

        return self::$_instance;
    }

    public function toValue($value) {
        self::$currentValue = $value;
        return $this;
    }

    public function add($value) {
        self::$currentValue = self::$currentValue + $value;
        return $this;
    }

    public function subtract($value) {
        self::$currentValue = self::$currentValue - $value;
        return $this;
    }

    public function result() {
        return self::$currentValue;
    }
}

// Example Usage:
$result = TestClass::getInstance ()
    ->toValue(5)
    ->add(3)
    ->subtract(2)
    ->add(8)
    ->result();

0 votes

public function result() { return $this::$value; } cette ligne est-elle censée être public function result() { return $this::$currentValue; } ? ???

0 votes

Cela ne fonctionnera pas dès que vous voudrez en utiliser plusieurs ensemble. $a = TestClass::getInstance()->toValue(3)->add(5); $b = TestClass::getInstance()->toValue(7)->add($a->result()); echo $b->result(); Vous obtiendrez 14 au lieu de 15. Ne manipulez pas l'argent avec ce calcul.

2 votes

La définition du constructeur private __construct () { } devrait être private function __construct () { } . Aussi, return $this::$currentValue; devrait être return self::$currentValue; .

51voto

Ariful Islam Points 158
class oop{
    public static $val;

    public static function add($var){
        static::$val+=$var;
        return new static;
    }

    public static function sub($var){
        static::$val-=$var;
        return new static;
    }

    public static function out(){
        return static::$val;
    }

    public static function init($var){
        static::$val=$var;
        return new static;      
    }
}

echo oop::init(5)->add(2)->out();

1 votes

Je pense que, pour ce qui est de la syntaxe (et non des meilleures pratiques de codage), c'est la meilleure réponse à cette question.

1 votes

Il manque à cette réponse son explication pédagogique.

32voto

sectus Points 6779

Un peu de code fou sur php5.3... juste pour le plaisir.

namespace chaining;
class chain
    {
    static public function one()
        {return get_called_class();}

    static public function two()
        {return get_called_class();}
    }

${${${${chain::one()} = chain::two()}::one()}::two()}::one();

11voto

Camilo Díaz Repka Points 2682

Si toValue(x) renvoie un objet, vous pourriez faire comme ceci :

$value = TestClass::toValue(5)->add(3)->substract(2)->add(8);

A condition que toValue renvoie une nouvelle instance de l'objet, et que chaque méthode suivante le mute, en renvoyant une instance de $this.

3voto

Phobis Points 3070

Vous pouvez toujours utiliser la première méthode comme méthode statique et les autres comme méthodes d'instance :

$value = Math::toValue(5)->add(3)->subtract(2)->add(8)->result();

Ou mieux encore :

 $value = Math::eval(Math::value(5)->add(3)->subtract(2)->add(8));

class Math {
     public $operation;
     public $operationValue;
     public $args;
     public $allOperations = array();

     public function __construct($aOperation, $aValue, $theArgs)
     {
       $this->operation = $aOperation;
       $this->operationValue = $aValue;
       $this->args = $theArgs;
     }

     public static function eval($math) {
       if(strcasecmp(get_class($math), "Math") == 0){
            $newValue = $math->operationValue;
            foreach ($math->allOperations as $operationKey=>$currentOperation) {
                switch($currentOperation->operation){
                    case "add":
                         $newvalue = $currentOperation->operationValue + $currentOperation->args;
                         break;
                    case "subtract":
                         $newvalue = $currentOperation->operationValue - $currentOperation->args;
                         break;
                }
            }
            return $newValue;
       }
       return null;
     }

     public function add($number){
         $math = new Math("add", null, $number);
         $this->allOperations[count($this->allOperations)] &= $math;
         return $this;
     }

     public function subtract($number){
         $math = new Math("subtract", null, $number);
         $this->allOperations[count($this->allOperations)] &= $math;
         return $this;
     }

     public static function value($number){
         return new Math("value", $number, null);
     }
 }

Juste pour info, j'ai écrit ceci à partir de ma tête (ici même sur le site). Il se peut donc qu'il ne fonctionne pas, mais c'est l'idée. J'aurais aussi pu faire un appel récursif à la méthode eval, mais j'ai pensé que ce serait plus simple. N'hésitez pas à me faire savoir si vous souhaitez que je développe ou que je vous apporte toute autre aide.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X