An easier way to write a calculator class in OOP PHP

I created a class called Calculator with the function of adding, subtracting, multiplying and division. The calculator is limited to adding two numbers and returning the result. I am relatively new to OOP, would like to get some input on the class, if I made a long route, and if I did, there is another way to simplify the class.

Here is the code:

class Calculator { private $_val1 , $_val2; public function __construct($val1, $val2){ $this->_val1 = $val1; $this->_val2 = $val2; } public function add(){ return $this->_val1 + $this->_val2; } public function subtract(){ return $this->_val1 - $this->_val2; } public function multiply (){ return $this->_val1 * $this->_val2; } public function divide () { return $this->_val1 / $this->_val2; } } $calc = new Calculator(3,4); echo "<p>3 + 4 = ".$calc->add(). "</p>"; $calc = new Calculator (15,12); echo "<p>15 - 12 = ".$calc->subtract(). "</p>"; $calc = new Calculator (20,2); echo "<p> 20 * 2 = ".$calc->multiply(). "</p>"; $calc = new Calculator (20,2); echo "<p> 20 / 2 = ".$calc ->divide(). "</p>"; 
+7
source share
6 answers

IMHO, you should use Polymorphism.
This video can help you understand this principle.

Here is my way of thinking.

First, define an interface for any operations you need.

 interface OperationInterface { public function evaluate(array $operands = array()); } 

Then create a calculator holder

 class Calculator { protected $operands = array(); public function setOperands(array $operands = array()) { $this->operands = $operands; } public function addOperand($operand) { $this->operands[] = $operand; } /** * You need any operation that implement the given interface */ public function setOperation(OperationInterface $operation) { $this->operation = $operation; } public function process() { return $this->operation->evaluate($this->operands); } } 

Then you can define an operation, for example, adding

 class Addition implements OperationInterface { public function evaluate(array $operands = array()) { return array_sum($operands); } } 

And you would use it like:

 $calculator = new Calculator; $calculator->setOperands(array(4,2)); $calculator->setOperation(new Addition); echo $calculator->process(); // 6 

For this purpose, if you want to add some new behavior or change an existing one, simply create or edit a class.

For example, say you want to work with the module

 class Modulus implements OperationInterface { public function evaluate(array $operands = array()) { $equals = array_shift($operands); foreach ($operands as $value) { $equals = $equals % $value; } return $equals; } } 

Then

 $calculator = new Calculator; $calculator->setOperands(array(4,2)); $calculator->setOperation(new Addition); // 4 + 2 echo $calculator->process(); // 6 $calculator->setOperation(new Modulus); // 4 % 2 echo $calculator->process(); // 0 $calculator->setOperands(array(55, 10)); // 55 % 10 echo $calculator->process(); // 5 

This solution allows your code to be a third-party library.

If you plan to reuse this code or give it as a library, the user will not modify your source code in any way.
But what if he needs a Substraction or BackwardSubstraction method that is not defined?

He just needs to create his own Substraction class in his project, which implements OperationInterface to work with your library.

Easier to read

When searching in the project architecture it’s easier to see such a folder

 - app/ - lib/ - Calculator/ - Operation/ - Addition.php - Modulus.php - Substraction.php - OperationInterface.php - Calculator.php 

And immediately find out which file contains the desired behavior.

+7
source

I don't think a simple calculator is a good example for OOP. An object needs both a set of methods and a set of variables that represent its state, and can be used to distinguish between instances of the object. I would suggest trying to make "moody" calculators. A happy mood calculator will add 2 to each result, and an angry calculator will subtract 2 from each result.

+2
source

I would do something like this

 interface Evaluable { public function evaluate(); } class Value implements Evaluable { private $value; public function __construct($value) { $this->value = $value; } public function evaluate() { return $this->value(); } } class Node implements Evaluable { protected $left; protected $right; public function __construct(Evaluable $left, Evaluable $right) { $this->left = $left; $this->right = $right; } } class SumNode extends Node { public function evaluate() { return $this->left->evaluate() + $this->right->evaluate(); } } $op = new SumNode(new Value(2), new Value(3)); $result = $op->evaluate(); 

This way you can easily add new operations

 class SubNode extends Node { public function evaluate() { return $this->left->evaluate() - $this->right->evaluate(); } } 

And chain operations like this

 $sum1 = new SumNode(new Value(5), new Value(3)); $sum2 = new SumNode(new Value(1), new Value(2)); $op = new SubNode($sum1, $sum2); $result = $op->evaluate(); 
+2
source

In the general case, we do not fix the value in this class. Your methods should take their 2 values ​​with arguments instead of choosing private members.

As below:

 public function add($v1, $v2) { return $v1 + $v2; } 

Thus, the Calculator becomes a tool, and we do not need to select this type of object. Therefore, calculator methods must be static .

 public static function add($v1, $v2) { return $v1 + $v2; } 

Thus, all you need to call is Calculator::add(1, 2) . You can find such classes everywhere. Like Vector, Matrice in math or 3D. Or write an output or something like that.

Remember that this is a way to do this, neither better nor worse.

+1
source

you should probably do something like

 $calc = new Calculator(); $calc->sum($x, $y, $z); $calc->substract($x, $y); .... 

Take a look at this example. You can give as many arguments as this using func_num_args ()

 <?php function foo() { $numargs = func_num_args(); echo "Number of arguments: $numargs\n"; } foo(1, 2, 3); ?> // output: Number of arguments: 3 
0
source

There are many solutions to this problem, here is one of them:

  <? class Calculator { /** * @var float */ /** * @var float */ private $_val1, $_val2; /** * @var int */ private static $_result = 0; /** * @param $val1 * @param $val2 */ public function __construct($val1 = '', $val2 = '') { if ((!empty($val1) && !empty($val2)) && (!is_numeric($val1) && !is_numeric($val2))) { $this->_val1 = (float)$val1; $this->_val2 = (float)$val2; } } /** * @param $val1 */ public function setVal1($val1) { $this->_val1 = (float)$val1; } /** * @param $val2 */ public function setVal2($val2) { $this->_val2 = (float)$val2; } /** * @param string $operator * * @return float|int|string */ public function getResult($operator = '') { if (is_numeric($this->_val1) && is_numeric($this->_val2)) { switch ($operator) { case '+': self::$_result = $this->_val1 + $this->_val2; break; case '-': self::$_result = $this->_val1 - $this->_val2; break; case '*': self::$_result = $this->_val1 * $this->_val2; break; case '/': self::$_result = $this->_val1 / $this->_val2; break; } } else { echo 'Alert alert alert)) some of operands not set or not number'; } return self::$_result; } } 

And here is a nice solution https://gist.github.com/cangelis/1442951

0
source

All Articles