在OOP PHP中编写计算器类的更简单方法

时间:2013-04-17 12:21:35

标签: php oop

我创建了一个名为Calculator的类,它带有加,减,乘和除功能。计算器仅限于添加两个数字并返回结果。 我对OOP比较陌生,希望在课堂上得到一些输入,我是否采用了漫长的路线,如果我做的话还有另一种简化课程的方法。

以下是代码:

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>";

6 个答案:

答案 0 :(得分:8)

恕我直言,你应该使用多态性 This Video可以帮助您理解这一原则

这是我的思维方式。

首先,为您需要的任何操作定义接口

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

然后,创建计算器持有人

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);
    }
}

然后您可以定义一个操作,例如,添加

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

你会像以下一样使用它:

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

echo $calculator->process(); // 6

有了这一点,如果您想添加任何新行为或修改现有行为,只需创建或编辑一个类。

例如,假设你想要一个模数运算

class Modulus implements OperationInterface
{
    public function evaluate(array $operands = array())
    {
        $equals = array_shift($operands);

        foreach ($operands as $value) {
            $equals = $equals % $value;
        }

        return $equals;
    }
}

然后,

$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

此解决方案允许您的代码成为第三方库

如果您打算重复使用此代码或将其作为库提供,则用户无论如何都不会修改您的源代码
但是如果他想要一个未定义的SubstractionBackwardSubstraction方法呢?

他只需要在他的项目中创建自己的Substraction类,该类实现OperationInterface以便与您的库一起工作。

更容易阅读

在查看项目架构时,更容易看到像这样的文件夹

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

立即知道哪个文件包含所需的行为。

答案 1 :(得分:2)

我认为普通计算器不是OOP的好例子。对象需要一组方法和一组表示其状态的变量,并且可用于区分对象的实例。我建议尝试制作“喜怒无常”的计算器。心情愉快的计算器将为每个结果添加2,愤怒的计算器将从每个结果中减去2。

答案 2 :(得分:2)

我会做这样的事情

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();

这样您就可以轻松添加新操作

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

像这样的连锁经营

$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();  

答案 3 :(得分:1)

一般来说,我们不会在这类课程中确定价值。 您的方法应该通过参数取两个值,而不是选择私有成员。

如下所示:

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

因此,Calculator成为一种工具,我们不需要分配这种对象。 这就是计算器方法应该静态的原因。

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

通过这种方式,您需要调用的只是Calculator::add(1, 2)。 你到处都可以找到那种类。像Vector,Matrice在数学或3D中。或写入输出或类似的东西。

请记住,这是一种方法,无论是最好还是最差。

答案 4 :(得分:0)

你应该最终做类似

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

看看这个例子。你可以使用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

答案 5 :(得分:0)

这个任务有很多解决方案,其中之一就是:

 <?

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;
    }
}

这是一个很好的解决方案https://gist.github.com/cangelis/1442951