6

PHP では、2D 配列とクラスのどちらを使用するのが適切ですか? これが意味することの例を含めました。

// Using a class
class someClass
{
    public  $name;
    public  $height;
    public  $weight;

    function __construct($name, $height, $weight)
    {
        $this -> name       = $name;
        $this -> height = $height;
        $this -> weight = $weight;
    }
}

$classArray[1] = new someClass('Bob', 10, 20);
$classArray[2] = new someClass('Fred', 15, 10);
$classArray[3] = new someClass('Ned', 25, 30);


// Using a 2D array
$normalArray[1]['name'] = 'Bob';
$normalArray[1]['height']   = 10;
$normalArray[1]['weight']   = 20;

$normalArray[2]['name'] = 'Fred';
$normalArray[2]['height']   = 15;
$normalArray[2]['weight']   = 10;

$normalArray[3]['name'] = 'Ned';
$normalArray[3]['height']   = 25;
$normalArray[3]['weight']   = 30;

誰かが出てきて、授業が遅すぎることを示さないと仮定すると、授業が勝つように見えます。

どの回答を受け入れるべきかわかりません。すべてに賛成票を投じました。


1 つは 2D 配列 (この質問が投稿される前に作成) を使用し、もう 1 つはクラスを使用しており、クラスはより優れたコードを生成すると言わざるを得ません。どれだけのオーバーヘッドが発生するかはわかりませんが、コード自体の改善に匹敵するとは思えません。

私をより良いプログラマーにする手助けをしてくれてありがとう。

4

9 に答える 9

9

上で構築した「クラス」は、ほとんどの人が他の言語で構造体を使用するものです。PHP でパフォーマンスにどのような影響があるかはわかりませんが、オブジェクトのインスタンス化はおそらくここでは少しだけコストがかかると思います。

そうは言っても、コストが比較的低い場合は、オブジェクトの管理が少し簡単になると思います。

タイトルとあなたの質問に基づいて次のように言っているだけですが、クラスにはメソッドとアクセス制御の利点もあることに注意してください。したがって、人々が重みを負の数に変更しないようにしたい場合は、weightフィールドを非公開にして、 や などのいくつかのアクセサ メソッドを提供getWeight()できますsetWeight()。内部setWeight()では、次のように値のチェックを行うことができます。

public function setWeight($weight)
{
    if($weight >= 0)
    {
        $this->weight = $weight;
    }
    else
    {
        // Handle this scenario however you like
    }
}
于 2008-08-23T10:52:51.727 に答える
4

それは、「より良い」という言葉が何を意味するかによって異なります。オブジェクト指向の方法 (クラスを使用) を選択します。これは、(少なくとも私の意見では) よりクリーンなコードになることがわかったからです。ただし、そのオプションの速度ペナルティがどの程度になるかはわかりません。

于 2008-08-23T10:42:51.347 に答える
4

一般的に、私は次のルールに従います。

1) アプリケーションの複数の部分でデータ構造を使用する場合は、クラスにします。

2) アプリケーションの一部でデータをすばやく処理するために使用している場合は、2D 配列にします。

于 2008-08-23T10:56:10.427 に答える
3

私が主に考えているのは速度です。ここにあるものよりも複雑なものについては、おそらくクラスを使用しますが、問題は、クラスのコストはいくらですか?

これは時期尚早の最適化のようです。アプリケーションが実際のパフォーマンスに影響を与えることはありませんが、クラスを使用すると getter メソッドと setter メソッドを使用できるため、通常はコードのカプセル化とコードの再利用に適しています。

配列を使用すると、コードの読み取りと保守が難しくなり、コードの単体テストを簡単に行うことができなくなります。適切なクラス構造を使用すると、他の開発者がそれを引き受ける必要があるかどうかを簡単に理解できるはずです。

後でこれらを操作するために他のメソッドを追加する必要が生じた場合、拡張するアーキテクチャはありません。

于 2008-08-23T11:10:43.370 に答える
2

あなたが持っているクラスは、OO 用語では実際のクラスではありません。インスタンス変数のスペースを取るように構築されているだけです。

そうは言っても、おそらく速度にはあまり問題はありません-あなたの例ではスタイルの問題です。

興味深いのは、オブジェクトを実際の「人」クラスに構築し、その人クラスに必要な他の属性とアクションについて考えた場合、スタイルのパフォーマンスだけでなく、コードを書くことにも気付くでしょう。スピード性能も。

于 2008-08-23T12:12:18.323 に答える
0

コードでこれらの属性(名前/高さ/重み)を操作する多くの関数を使用している場合は、クラスを使用することをお勧めします。

于 2008-08-23T15:42:51.717 に答える
0

@リチャード・ヴァルノ

(小さなバグを修正した後)正確なコードを実行しましたが、あなたとはかなり異なる結果が得られました。私のPHP 5.3.17インストールでは、クラスはかなり実行されました。

配列時間 = 0.69054913520813 授業時間 = 1.1762700080872

合計配列時間 (これまで) = 0.69054508209229(100,000 回の反復) 合計クラス時間 (これまで) = 1.1762590408325(100,000 回の反復)

配列時間 = 0.99001502990723 授業時間 = 1.22034907341

合計配列時間 (これまで) = 1.6805560588837(100,000 回の反復) 合計クラス時間 (これまで) = 2.3966031074524(100,000 回の反復)

配列時間 = 0.99191808700562 授業時間 = 1.2245700359344

合計配列時間 (これまで) = 2.6724660396576(100,000 回の反復) 合計クラス時間 (これまで) = 3.6211669445038(100,000 回の反復)

配列時間 = 0.9890251159668 授業時間 = 1.2246470451355

合計配列時間 (これまで) = 3.661484003067 (100,000 回の反復) 合計クラス時間 (これまで) = 4.8458080291748 (100,000 回の反復)

配列時間 = 0.99573588371277 授業時間 = 1.1242771148682

合計配列時間 (これまで) = 4.6572148799896 (100,000 回の反復) 合計クラス時間 (これまで) = 5.9700801372528 (100,000 回の反復)

配列時間 = 0.88518786430359 授業時間 = 1.1427340507507

合計配列時間 (これまで) = 5.5423986911774(100,000 回の反復) 合計クラス時間 (これまで) = 7.1128082275391(100,000 回の反復)

配列時間 = 0.87605404853821 授業時間 = 0.95899105072021

合計配列時間 (これまで) = 6.4184486865997 (100,000 回の反復) 合計クラス時間 (これまで) = 8.0717933177948 (100,000 回の反復)

配列時間 = 0.73414516448975 授業時間 = 1.0223190784454

合計配列時間 (これまで) = 7.1525888442993 (100,000 回の反復) 合計クラス時間 (これまで) = 9.0941033363342 (100,000 回の反復)

配列時間 = 0.95230412483215 授業時間 = 1.059828042984

合計配列時間 (これまで) = 8.1048839092255(100,000 回の反復) 合計クラス時間 (これまで) = 10.153927326202(100,000 回の反復)

配列時間 = 0.75814390182495 授業時間 = 0.84455919265747

合計配列時間 (これまで) = 8.8630249500275(100,000 回の反復) 合計クラス時間 (これまで) = 10.998482465744(100,000 回の反復) 合計回数:

合計配列時間 = 8.8630249500275(1,000,000 回の反復) 合計クラス時間 = 10.998482465744(1,000,000 回の反復)

于 2012-11-03T20:46:54.423 に答える
0

Teifion さん、クラスを配列の単なる代替として使用する場合、OOP にはほど遠いものです。OOP の本質は、オブジェクトが知識と責任を持ち、実際に物事を行うことができ、他のクラスと協力できることです。あなたのオブジェクトは知識しか持っておらず、アイドル状態で存在する以外に何もできませんが、永続化プロバイダー (データベースに/から自分自身を格納/取得する方法を知っているオブジェクト) の良い候補のようです。

パフォーマンスについても心配しないでください。PHP のオブジェクトは高速で軽量であり、一般的にパフォーマンスは過大評価されています。あいまいでデバッグや修正が難しいコードを使ってプログラムの時間をマイクロ秒節約するよりも、適切なアプローチを使用してプログラマーとしての時間を節約する方が安上がりです。

于 2008-08-29T08:37:50.973 に答える
0

配列とクラスの時間を計測するほとんどのテストは、それらのインスタンス化のみをテストします。実際に彼らと何かを始めたら。

私は、パフォーマンスがはるかに優れていたため、配列のみを使用する「純粋主義者」でした。クラスを使用しないという余分な手間を正当化するために、次のコードを書きました(プログラマーにとっては簡単ですが)

私は結果に非常に驚いたと言っておきましょう!

    <?php
$rx = "";
$rt = "";
$rf = "";

$ta = 0; // total array time
$tc = 0; // total class time

// flip these to test different attributes
$test_globals = true;
$test_functions = true;
$test_assignments = true;
$test_reads = true;


// define class


class TestObject
{
  public $a;
  public $b;
  public $c;
  public $d;
  public $e;
  public $f;

  public function __construct($a,$b,$c,$d,$e,$f)
  {
    $this->a = $a;
    $this->b = $b;
    $this->c = $c;
    $this->d = $d;
    $this->e = $e;
    $this->f = $f;
  }

  public function setAtoB()
  {
      $this->a = $this->b;
  }
}

// begin test

echo "<br>test reads: " . $test_reads;
echo "<br>test assignments: " . $test_assignments;
echo "<br>test globals: " . $test_globals;
echo "<br>test functions: " . $test_functions;
echo "<br>";

for ($z=0;$z<10;$z++)
{
    $starta = microtime(true);

    for ($x=0;$x<100000;$x++)
    {
        $xr = getArray('aaa','bbb','ccccccccc','ddddddddd','eeeeeeee','fffffffffff');

        if ($test_assignments)
        {
            $xr['e'] = "e";
            $xr['c'] = "sea biscut";
        }

        if ($test_reads)
        {
            $rt = $x['b'];
            $rx  = $x['f'];
        }

        if ($test_functions) { setArrAtoB($xr); }
        if ($test_globals) { $rf = glb_arr(); }
    }
    $ta = $ta + (microtime(true)-$starta);
    echo "<br/>Array time = " . (microtime(true)-$starta) . "\n\n";


    $startc = microtime(true);

    for ($x=0;$x<100000;$x++)
    {
        $xo = new TestObject('aaa','bbb','ccccccccc','ddddddddd','eeeeeeee','fffffffffff');

        if ($test_assignments)
        {
            $xo->e = "e";
            $xo->c = "sea biscut";
        }

        if ($test_reads)
        {
            $rt = $xo->b;
            $rx = $xo->f;
        }

        if ($test_functions) { $xo->setAtoB(); }
        if ($test_globals) { $xf = glb_cls(); }
    }

    $tc = $tc + (microtime(true)-$startc);
    echo "<br>Class time = " . (microtime(true)-$startc) . "\n\n";

    echo "<br>";
    echo "<br>Total Array time (so far) = " . $ta . "(100,000 iterations) \n\n";
    echo "<br>Total Class time (so far) = " . $tc . "(100,000 iterations) \n\n";
    echo "<br>";

}
echo "TOTAL TIMES:";
echo "<br>";
echo "<br>Total Array time = " . $ta . "(1,000,000 iterations) \n\n";
echo "<br>Total Class time = " . $tc . "(1,000,000 iterations)\n\n";


// test functions

function getArray($a,$b,$c,$d,$e,$f)
{
    $arr = array();
    $arr['a'] = $a;
    $arr['b'] = $b;
    $arr['c'] = $c;
    $arr['d'] = $d;
    $arr['d'] = $e;
    $arr['d'] = $f;
    return($arr);
}

//-------------------------------------

function setArrAtoB($r)
{
    $r['a'] = $r['b'];
}

//-------------------------------------

function glb_cls()
{
    global $xo;

    $xo->d = "ddxxdd";
    return ($xo->f);
}

//-------------------------------------

function glb_arr()
{
    global $xr;

    $xr['d'] = "ddxxdd";
    return ($xr['f']);
}

//-------------------------------------

?>

テスト読み取り: 1 テスト割り当て: 1 テスト グローバル: 1 テスト機能: 1

配列時間 = 1.58905816078 クラス時間 = 1.11980104446 合計配列時間 (これまで) = 1.58903813362(100,000 回の反復) 合計クラス時間 (これまで) = 1.11979603767(100,000 回の反復)

配列時間 = 1.02581000328 クラス時間 = 1.22492313385 合計配列時間 (これまで) = 2.61484408379(100,000 回の反復) 合計クラス時間 (これまで) = 2.34471416473(100,000 回の反復)

配列時間 = 1.29942297935 クラス時間 = 1.18844485283 合計配列時間 (これまで) = 3.91425895691(100,000 回の反復) 合計クラス時間 (これまで) = 3.5331492424(100,000 回の反復)

配列時間 = 1.28776097298 クラス時間 = 1.02383089066 合計配列時間 (これまで) = 5.2020149231(100,000 回の反復) 合計クラス時間 (これまで) = 4.55697512627(100,000 回の反復)

配列時間 = 1.31235599518 クラス時間 = 1.38880181313 合計配列時間 (これまで) = 6.51436591148(100,000 回の反復) 合計クラス時間 (これまで) = 5.94577097893(100,000 回の反復)

配列時間 = 1.3007349968 クラス時間 = 1.07644081116 合計配列時間 (これまで) = 7.81509685516(100,000 回の反復) 合計クラス時間 (これまで) = 7.02220678329(100,000 回の反復)

配列時間 = 1.12752890587 クラス時間 = 1.07106018066 合計配列時間 (これまで) = 8.94262075424(100,000 回の反復) 合計クラス時間 (これまで) = 8.09326195717(100,000 回の反復)

配列時間 = 1.08890199661 クラス時間 = 1.09139609337 合計配列時間 (これまで) = 10.0315177441(100,000 回の反復) 合計クラス時間 (これまで) = 9.18465089798(100,000 回の反復)

配列時間 = 1.6172170639 クラス時間 = 1.14714384079 合計配列時間 (これまで) = 11.6487307549(100,000 回の反復) 合計クラス時間 (これまで) = 10.3317887783(100,000 回の反復)

配列時間 = 1.53738498688 クラス時間 = 1.28127002716 合計配列時間 (これまで) = 13.1861097813(100,000 回の反復) 合計クラス時間 (これまで) = 11.6130547523(100,000 回の反復)

合計回数: 合計配列時間 = 13.1861097813(1,000,000 回の反復) 合計クラス時間 = 11.6130547523(1,000,000 回の反復)

したがって、どちらの方法でも、違いはごくわずかです。グローバルにアクセスし始めると、クラスが実際に少し速くなることに非常に驚きました。

しかし、私を信用しないでください。自分で実行してください。個人的には、高性能アプリケーションでクラスを使用することについて、完全に罪悪感を感じなくなりました。:D

于 2010-12-31T18:03:13.080 に答える