我创建了一个名为Calculator的类,具有加、减、乘、除功能。计算器只能将两个数字相加并返回结果。我是相对较新的面向对象,想在类上得到一些输入,我是否采取了漫长的路线,如果我这样做,是否有另一种方法来简化类。
代码如下:
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>";
IMHO,您应该使用多态性。
这个视频可以帮助你理解这个原理
这是我的思考方式。
首先,为您需要的任何操作定义一个接口
interface OperationInterface
{
public function evaluate(array $operands = array());
}
然后创建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);
}
}
然后可以定义一个操作,例如,加法
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
这个解决方案允许你的代码成为一个第三方库
如果你打算重用这些代码或将其作为库提供,用户无论如何都不会修改你的源代码。
但是如果他想要一个没有定义的Substraction
或BackwardSubstraction
方法呢?
他只需要在他的项目中创建他自己的Substraction
类,它实现了OperationInterface
以便与您的库一起工作。
更容易阅读
查看项目架构时,更容易看到这样的文件夹
- app/
- lib/
- Calculator/
- Operation/
- Addition.php
- Modulus.php
- Substraction.php
- OperationInterface.php
- Calculator.php
并立即知道哪个文件包含所需的行为
我不认为一个普通的计算器是一个很好的面向对象的例子。一个对象既需要一组方法,也需要一组变量来表示它的状态,并且可以用来区分对象的实例。我建议尝试制作"喜怒无常"的计算器。心情愉快的计算器会在每个结果上加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();
一般来说,我们不会在这类中固定值。你的方法应该通过参数获取它们的两个值,而不是选择私有成员。
像下面这样:
public function add($v1, $v2)
{
return $v1 + $v2;
}
因此,Calculator变成了一个工具,我们不需要分配这类对象。这就是为什么Calculators的方法应该是static。
public static function add($v1, $v2)
{
return $v1 + $v2;
}
这样,你只需要调用Calculator::add(1, 2)
。这类课程随处可见。比如数学中的矢量、矩阵或3D。或写入输出或类似的内容
记住,这是一种方法,既不是最好的也不是最差的。
你最终应该做一些像
$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
这个任务有很多解决方案,这里是其中之一:
<?
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