8

加算、減算、乗算、除算機能を備えた Calculator というクラスを作成しました。電卓は、2 つの数値を加算して結果を返すことに制限されています。私は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>";
4

6 に答える 6

8

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

このソリューションにより、コードをサードパーティのライブラリにすることができます

このコードを再利用したり、ライブラリとして提供したりする場合、ユーザーはソース コードを変更することは決してありません。しかし、定義されていないまたはメソッドが 必要
な場合はどうすればよいでしょうか?SubstractionBackwardSubstraction

彼は自分のプロジェクトで独自のクラスを作成するだけで済みます。これは、ライブラリを操作するためにSubstraction実装されます。OperationInterface

読みやすくなっています

プロジェクトのアーキテクチャを見ると、このようなフォルダーが見やすいです

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

そして、どのファイルに目的の動作が含まれているかがすぐにわかります。

于 2013-04-17T12:44:17.873 に答える
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();  
于 2013-04-17T13:42:55.593 に答える
2

単純な電卓は OOP の良い例ではないと思います。オブジェクトには、メソッドのセットとその状態を表す変数のセットの両方が必要であり、オブジェクトのインスタンスを区別するために使用できます。「不機嫌な」電卓を作ってみることをお勧めします。機嫌の良い電卓は各結果に 2 を加算し、怒っている電卓は各結果から 2 を減算します。

于 2013-04-17T12:42:16.523 に答える
1

通常、この種のクラスでは値を固定しません。メソッドは、プライベート メンバーを選択するのではなく、引数によって 2 つの値を取得する必要があります。

次のように:

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

したがって、電卓はツールになり、この種のオブジェクトを割り当てる必要はありません。そのため、Calculators メソッドはstaticにする必要があります。

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

このように、呼び出す必要があるのはCalculator::add(1, 2). そういうクラスはどこにでもあります。ベクトル、数学または 3D の行列のように。または、出力などに書き込みます。

覚えておいてください、それはそれを行うための方法であり、最善でも最悪でもありません.

于 2013-04-17T12:32:37.137 に答える
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
于 2013-04-17T12:32:07.300 に答える
0

このタスクには多くの解決策があります。そのうちの 1 つを次に示します。

 <?

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

于 2013-04-17T13:04:18.680 に答える