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

在OOP PHP中编写计算器类的更简单方法,php,oop,Php,Oop,我创建了一个名为Calculator的类,带有加、减、乘和除函数。计算器仅限于将两个数字相加并返回结果。 我对OOP比较陌生,希望获得一些关于类的输入,我是否走了很长的路,如果我走了,是否有其他方法来简化类 代码如下: class Calculator { private $_val1 , $_val2; public function __construct($val1, $val2){ $this->_val1 = $val1; $th

我创建了一个名为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>";
类计算器{
私人$\u val1,$\u val2;
公共函数构造($val1,$val2){
$this->_val1=$val1;
$this->_val2=$val2;
}
公共功能添加(){
返回$this->_val1+$this->_val2;
}
公共函数减法(){
返回$this->_val1-$this->_val2;
}
公共函数乘法(){
返回$this->_val1*$this->_val2;
}
公共职能划分(){
返回$this->_val1/$this->_val2;
}
}
$calc=新计算器(3,4);
echo“3+4=”.$calc->add()。“

”; $calc=新计算器(15,12); echo“15-12=”.$calc->subtract()。“

”; $calc=新计算器(20,2); echo“20*2=”.$calc->multiply()。“

”; $calc=新计算器(20,2); echo“20/2=”.$calc->divide()。“

”;
你可能会做这样的事情

$calc = new Calculator();
$calc->sum($x, $y, $z);
$calc->substract($x, $y);
....
看看这个例子。可以使用func_num_args()给出任意数量的参数


//输出:参数数:3

一般来说,我们不会在此类类中固定值。 您的方法应该按参数获取它们的2个值,而不是选择私有成员

例如:

public function add($v1, $v2)
{
    return $v1 + $v2;
}
因此,计算器成为了一种工具,我们不需要分配这种对象。 这就是为什么计算器方法应该是静态的

public static function add($v1, $v2)
{
    return $v1 + $v2;
}
这样,您只需调用
Calculator::add(1,2)
。 你可以在任何地方找到这样的课程。就像数学或3D中的向量、矩阵一样。或者写入输出或类似的内容


记住,这是一种方法,既不是最好的也不是最坏的。

我不认为简单的计算器是OOP的好例子。一个对象需要一组方法和一组表示其状态的变量,并且可以用来区分对象的实例。我建议尝试制作“穆迪”计算器。心情愉快的计算器会给每个结果加2,心情愤怒的计算器会从每个结果中减去2

IMHO,您应该使用多态性。
可以帮助你理解这个原则

这是我的想法

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

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

此解决方案允许您的代码成为第三方库 如果您计划重用此代码或将其作为库分发,用户无论如何都不会修改您的源代码。
但是如果他想要一个未定义的
减法
后向减法
方法怎么办

他只需要在他的项目中创建自己的
减法
类,该类实现
操作接口
,以便使用您的库

它更容易阅读 在项目架构中查看时,更容易看到这样的文件夹

- app/
    - lib/
        - Calculator/
            - Operation/
                - Addition.php
                - Modulus.php
                - Substraction.php
            - OperationInterface.php
            - Calculator.php
$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();  

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

此任务有很多解决方案,下面是其中之一:

 <?

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

我会这样做

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();
    }
}
还有像这样的连锁经营

- app/
    - lib/
        - Calculator/
            - Operation/
                - Addition.php
                - Modulus.php
                - Substraction.php
            - OperationInterface.php
            - Calculator.php
$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();  

请花一分钟将代码正确对齐。当代码乱七八糟时,几乎不可能读取它。请为您对齐它。:-)啊,对不起,我想我们是并行编辑的:)不妨使用一些链接功能来制作
echo$calculator->setoperans(数组(4,2))->setOperation(新添加)->process()可能?只需添加
返回$this
setOperands
setOperation
方法上我喜欢stackoverflow。我肯定会在开关中添加一个默认大小写(除了一个例外),以防止输入错误和未知操作数。此外,您应该抛出异常,而不是执行回显。如果没有异常,代码将返回未定义的结果,从而导致PHP错误消息和/或奇怪的行为。除此之外,关于chandresh_cool.的建议,请参见我的其他评论。。对于计算公式的简单实用函数(如本例),它们可能是一个好主意,但如果您希望您的类是可单元测试的,请不要过度使用静态方法。您可能喜欢阅读-这家伙的答案是肯定的“是”。我同意。我的答案和图基的相似。我们都看了Misko的精彩视频:pDid你真的检查了脚本?乍一看,您缺少两件事:
类节点
没有实现
求值()
方法,
类值
没有方法
值()
,只有属性
。但除此之外,得到图案的想法也很好!(Y) 哎呀,我刚刚想到,在PHP>=5.4上,可以在类扩展中实现“接口”方法。。。