-3

How can'i create a classe calculator witch can do ita differents operations like : addition , multiplication but with this format $test->two()->add()->one() ==> the result is 3.

Can you help me ?

thank you 


class Test 
{
    private $result;
    function __construct()
    {
        $this->result = 0;
    }
    
    function one()
    {
        $this->result = 1;
        return $this;
    }
    
    function two()
    {
        $this->result = 2;
        return $this;
    }
    
    function add()
    {
        $this->result += $this->result;
        return $this;
    }
    
    function getResult()
    {
        return $this->result;
    }
}

$test = new Test();
$a = $test->One()->add()->two();
var_dump($a->getResult());

I did this programm but i didn't had the correct response 

the result returned is 2 but i must have 3 (1+2)
ADyson
  • 57,178
  • 14
  • 51
  • 63
DevPhp20
  • 1
  • 1
  • 1
    You could just use: `2 + 1`. That will result in 3 as well. Isn't that simpler? – KIKO Software Oct 16 '20 at 14:23
  • Thanks Kiko for your response but i have a test to do with this format and i don't have any idea how i can do it. – DevPhp20 Oct 16 '20 at 14:26
  • 1
    OK, you're still learning. Well, the numbers and operators are methods of a class. These methods need to return `$this` so they can be chained. Inside your class you need to maintain the state of your calculator. Etc. Do these hints help? – KIKO Software Oct 16 '20 at 14:32
  • How i can do that ? can you please give me un exemple ? – DevPhp20 Oct 16 '20 at 14:35
  • do what exactly? Kiko outlines several steps. Where are you stuck? If you show us your existing class code, as it exists so far, it would be easier to make our suggestions more precise. – ADyson Oct 16 '20 at 14:37
  • No sorry, I think the whole idea here is that you figure the rest out yourself. This website is for real programming problems, and is not intended to take the hard part out of learning to program. – KIKO Software Oct 16 '20 at 14:37
  • KIKO , thanks i know that but i don't understand how i can do it for that i told you to take me a simple example. – DevPhp20 Oct 16 '20 at 14:41
  • Have a look here: https://stackoverflow.com/questions/3724112/php-method-chaining – KIKO Software Oct 16 '20 at 14:42
  • "i don't understand how i can do it" ...again, do **what** exactly? Make your functions return `$this`? Well `return $this;` at the end of your functions - hopefully this is reasonably obvious. "maintain state", well that's more tricky but basically you need to keep a record of what operations have been performed so far, and/or what the current value of the calculation is. Depends how you're wanting to use it. We don't know enough about your requirements to give you a precise suggestion. – ADyson Oct 16 '20 at 14:43
  • ADyson, if the numbers and operators are methods of a class and theses methods return $this. when i can do the addition for return a result – DevPhp20 Oct 16 '20 at 14:44
  • you'd have to have a separate function to get the actual result. e.g. `$test->two()->add()->one()->result()`. You can't have it both ways. Either it returns itself to allow chaining, or it returns the result. You need to decide. – ADyson Oct 16 '20 at 14:48
  • P.S. not sure about the `->one()`, `->two()` stuff. Are you going up to 9, to correspond to button presses or what? Otherwise it makes no sense, because clearly people will want to add larger numbers. Wouldn't something more like `->add(28)` make better sense? – ADyson Oct 16 '20 at 14:55
  • ADyson , i agree with you but the test like this just for the numbers for 0 to 9. I posted un example of my program witch the result is incorrect. you can help me please? – DevPhp20 Oct 16 '20 at 15:09
  • 1
    `$this->result = 2;` sets the result to exactly two. This overwrites any previous values. Doesn't make **any** sense to do this. And the add() bit also makes no sense, because you're a) trying to add result to _itself_, and b) by the logic you're wanting, you don't even know what the second thing to add is yet, because you haven't yet specified the two() call. This is another reason I'm saying the ->one(), ->two() stuff just doesn't work. I get that you want to make some sort of "readable" syntax, but the actual logic is completely backwards and unworkable. – ADyson Oct 16 '20 at 15:27
  • `$test->add(2)->add(1)->result()` would be both readable, and, crucially, _implementable_. – ADyson Oct 16 '20 at 15:30
  • ADyson, so how i can set the value of each number if i didn't do $this->result = 1 (one) or 2 (two)... – DevPhp20 Oct 16 '20 at 15:34
  • ADyson, i know this solution $test->add(2)->add(1)->result() and i'm agree with you but the test is like this $test->one()->add()->two() ==> gives 3 – DevPhp20 Oct 16 '20 at 15:36
  • " the test is like this"...well the test has failed. It doesn't work and can never work, as far as I can see. You can't "add" when you don't yet know what you're adding. And also as we discussed earlier you can't directly return 3 from the two() function - you always need a separate result function too - unless you make it so that two() is always the end of the chain, which seems ridiculous. Have you been told by someone else to make code that works using exactly this syntax, or is it just your own idea? – ADyson Oct 16 '20 at 15:39
  • `one()->two()->add()` could be made to work, if you make the one() and two() functions add values to a list of "pending" values inside the class, and then the ->add() function loops through the pending list of values and adds them to $result. That would make sense, because then add() knows what it's supposed to be adding up. And you could chain as many as you liked e.g. `one()->two()->thirty()->add()`. Just an idea. Dunno if that helps you or not. It still seems daft to have separate functions for each number though. – ADyson Oct 16 '20 at 15:51
  • Ok. So, I partially take back my previous statements. Here's an idea actually to make the original idea work: http://sandbox.onlinephpfunctions.com/code/106c9bd952204a02c398585aa4a85291fb0df8ef - it works on the basis that add() simply sends a "pending" operation, and that one() or two() (I've shortcut that to key($num) for simplicity though) actually carries out the last operation specified by add() or subtract(). It works by using PHP's ability to specify a function to call using a string value. Bit hacky but it seems to work. – ADyson Oct 16 '20 at 16:04
  • So it assumes that if you wrote e.g. one()->add()->two()->two() the second call to two() would also do an add, because that was the last operation specified (so the result would be 5 in that case), and also the initial operation is always "add" as well (although I guess you could allow that to be specified in the constructor). What do you think? Does that meet your requirements sufficiently? I can write it up as an answer instead of the current one, if you agree. I thought it was impossible, but actually it required a bit of lateral thinking (plus the aforementioned assumptions to hold). – ADyson Oct 16 '20 at 16:06
  • http://sandbox.onlinephpfunctions.com/code/0be629f803261c35017ae49a51fa24385978568d for a final demo. Once I'd made the comment about "pending" values, I realised it might be possible to have "pending" operations too. – ADyson Oct 16 '20 at 16:10

2 Answers2

0

Here is a solution.

It works on the basis that add() or subtract() doesn't directly carry out any work, it simply sets a "pending" operation, and that one() or two() (I've shortcut that style to key($num) for simplicity though, I think it's better and more flexible as well) actually does the the last operation specified by add() or subtract(), using the number specified in the input.

It works by using PHP's ability to specify a function to call using a string value. Bit hacky but it seems to work.

class Calculator 
{
    private $result;
    private $nextOp;
    
    function __construct()
    {
        $this->result = 0;
        $this->nextOp = "addVal";
    }
    
    function key($num)
    {
        $this->{$this->nextOp}($num);
        return $this;
    }
    
    function add()
    {
        $this->nextOp = "addVal";
        return $this;
    }
    
    function subtract()
    {
        $this->nextOp = "subtractVal";
        return $this;
    }
    
    private function addVal($num)
    {
        $this->result += $num;
    }
    
    private function subtractVal($num)
    {
        $this->result -= $num;
    }

    function result()
    {
        return $this->result;
    }
}

$test = new Calculator();
$a = $test->key(1)->add()->key(2)->key(3)->subtract()->key(2)->result();
var_dump($a);

This outputs 4.

N.B. It assumes that if you wrote e.g. key(1)->add()->key(2)->key(2) the second call to key(2) would also do an add, because that was the last operation specified (so the result would be 5 in that case), and also the initial operation is always add as well (although I guess you could allow that to be specified in the constructor). I don't know if these assumptions are acceptable in your scenario, you didn't specify what should happen if the user write something like this, or what the class should do with the initial value.

Live demo: http://sandbox.onlinephpfunctions.com/code/0be629f803261c35017ae49a51fa24385978568d

ADyson
  • 57,178
  • 14
  • 51
  • 63
0

this is my response. It's worked very fine

// Interface des opérations
interface Operation {
    public function plus();
    public function minus();
    public function divededInto();
    public function  times();
    public function doOperation($value);
}
// Class Calculator 
class Calculator implements Operation {
    private $result;
    private $operation;
    private $numbers;
        public function __construct($numbers) {
        $this->numbers = $numbers;
        $this->result = 0;
        $this->operation = null;
    }
   //Surcharge de la méthode __call
    public function __call($name, $arguments){
        $name = strtolower($name);
        $this->doOPeration($this->numbers[$name]);
        $this->operation = null;
        return $this;
    }
  // Exécution de l’opération  
    public function doOperation($value){
    switch ($this->operation ){
            case '+':
              $this->result += $value;
              break;    
             case '-':
              $this->result -= $value;
              break; 
              case '/':
              $this->result = intDiv($this->result,$value);
              break;
              case '*':
              $this->result *= $value;
              break;
              default : $this->result = $value;
        }
    }
DevPhp20
  • 1
  • 1