なぜ配列ではなくオブジェクトを返すのですか?


84

私はWordPressで多くの作業を行っていますが、配列よりもはるかに多くの関数がオブジェクトを返すことに気づきました。特に配列を要求しない限り、データベースの結果はオブジェクトとして返されます。エラーはオブジェクトとして返されます。WordPress以外では、ほとんどのAPIは配列ではなくオブジェクトを提供します。

私の質問は、なぜ配列の代わりにオブジェクトを使用するのかということです。ほとんどの場合、それはそれほど重要ではありませんが、場合によっては、オブジェクトを処理するだけでなく、頭を包むのが難しいと感じることがあります。オブジェクトを使用するパフォーマンス上の理由はありますか?

私は独学のPHPプログラマーです。私はリベラルアーツの学位を持っています。したがって、コンピュータサイエンスの基本的な側面が欠けている場合は、ご容赦ください。;)


5
オブジェクトの使用や機能ができないなど、オブジェクトの欠点に関して(少なくともキー=>値データの保存/返送に関して)、これについて興味があります。誰もそれについて言及していないようです、または私は何かを逃していますか?count()array_*()
ウェズリーマーチ2011

8
CountableまたはIteratorインターフェースを実装することにより、オブジェクトをカウント可能および反復可能にすることができます。php.net/manual/en/book.spl.phpもチェックしてください。
simshaun 2011

SPLがインストールされていて、オブジェクトクラスにカウント可能なインターフェイスを実装している場合はcount()、オブジェクトを呼び出すことができます。
SEから離れる人はいません

2
多くの場合、オブジェクトのコレクション、または配列で簡単にエミュレートされない種類のコレクションを返さないため、配列は意味がありません。他の値のシーケンスがあり、追加のセマンティクスが関連付けられていない場合は、神のために配列を返します-しかし、それはめったにないことがわかります。

8
@delnanなど:@Dennisは、通常の(整数インデックス)配列ではなく、連想配列(別名、辞書、別名、マップ)について話していることに注意してください。これらはPHPのコア機能であり、動的クラス(stdClass)とほぼ同じ目的を果たします。私は確かに「OOPに主に働くプログラマは、オブジェクト使用のセマンティクス好むので」この質問以外の答えを持っていることはないよ
ダニーPflughoeft - BlueRajaを

回答:


62

これらは私が一般的にオブジェクトを好む理由です:

  • オブジェクトには、データだけでなく機能も含まれています。
  • オブジェクトには(ほとんどの場合)事前定義された構造があります。これはAPI設計に非常に役立ちます。さらに、プロパティをパブリック、保護、またはプライベートとして設定できます。
  • オブジェクトは、オブジェクト指向開発により適しています。
  • ほとんどのIDEのオートコンプリートは、オブジェクトに対してのみ機能します。

ここに読むべきものがあります:


3
最初のリンクは良くないようですか?私はそれが機能することを意味しますが、別の領域にかかります
Geo

24

これは、大規模なソフトウェアプロジェクトに数年間取り組むまでは、おそらく深く理解することではありません。多くの新しいコンピュータサイエンス専攻は、すべての正しい言葉(カプセル化、データを使用した機能、および保守性)で答えを出しますが、それらすべてが優れている理由を本当に理解している人はほとんどいません。

いくつかの例を見てみましょう。

  • 配列が返された場合は、すべての値を事前に計算するか、より複雑な値を作成できる小さな値をたくさん返す必要があります。

WordPressの投稿のリストを返すAPIメソッドについて考えてみてください。これらの投稿にはすべて著者がいて、著者には名前、電子メールアドレス、さらには経歴のあるプロフィールさえあります。

配列内のすべての投稿を返す場合は、投稿IDの配列を返すように制限する必要があります。

[233, 41, 204, 111]

または、次のような大規模な配列を返します。

[ title: 'somePost', body: 'blah blah', 'author': ['name': 'billy', 'email': 'bill@bill.com', 'profile': ['interests': ['interest1', 'interest2', ...], 'bio': 'info...']] ]
[id: '2', .....]]

IDのリストを返す最初のケースは、その投稿に関する情報を取得するためにIDごとにAPI呼び出しを行う必要があるため、あまり役に立ちません。

2番目のケースでは、90%の時間で必要な情報よりもはるかに多くの情報を取得し、より多くの作業を実行します(特に、これらのフィールドのいずれかを構築するのが非常に複雑な場合)。

一方、オブジェクトは、必要なすべての情報へのアクセスを提供できますが、実際にはまだその情報を取得していません。フィールドの値の決定は、オブジェクトを使用するときに遅延して(つまり、値が必要なときに、事前にではなく)実行できます。

  • アレイは、意図したよりも多くのデータと機能を公開します

返される大規模な配列の例に戻ります。これで、誰かがpost配列内の各値を反復処理して出力するアプリケーションを作成する可能性があります。APIが更新されて、そのpost配列に要素が1つだけ追加された場合、アプリケーションコードは、おそらく印刷されるべきではない新しいフィールドを出力するため、壊れます。APIによって返されるpost配列内のアイテムの順序が変更されると、アプリケーションコードも破損します。したがって、配列を返すと、オブジェクトが作成しない可能性のあるあらゆる種類の依存関係が作成されます。

  • 機能性

オブジェクトは、その中に情報を保持して、便利な機能を提供できるようにします。たとえば、投稿オブジェクトは、前または次の投稿を返すのに十分スマートである可能性があります。アレイはあなたのためにそれを行うことができませんでした。

  • 柔軟性

上記のオブジェクトのすべての利点は、より柔軟なシステムを作成するのに役立ちます。


10

私の質問は、なぜ配列の代わりにオブジェクトを使用するのかということです。

おそらく2つの理由:

  • WordPressはかなり古いです
  • ほとんどの場合、配列はより高速で、より少ないメモリを使用します
  • シリアル化が簡単

オブジェクトを使用するパフォーマンス上の理由はありますか?

いいえ。しかし、他にも多くの理由があります。たとえば、次のとおりです。

  • オブジェクト(メソッド、クロージャなど)にロジックを格納できます
  • インターフェイスを使用してオブジェクト構造を強制することができます
  • IDEでのオートコンプリートの改善
  • 未定義ではない配列キーの通知は表示されません
  • 最終的には、任意のオブジェクトを簡単に配列に変換できます

OOP!= AOP :)

(たとえば、Rubyでは、すべてがオブジェクトです。PHPは、以前は手続き型/スクリプト言語でした。)


7

WordPress(および他のかなりの量のPHPアプリケーション)は、技術的な理由ではなく概念的な理由で、配列ではなくオブジェクトを使用します。

オブジェクト(stdClassのインスタンスだけであっても)は1つのものの表現です。WordPressでは、投稿、コメント、またはユーザーの可能性があります。一方、配列は物の集まりです。(たとえば、投稿のリスト。)

歴史的に、PHPは優れたオブジェクトサポートを備えていなかったため、配列は早い段階で非常に強力になりました。(たとえば、ゼロインデックスだけでなく任意のキーを持つ機能。)PHP 5で利用可能なオブジェクトのサポートにより、開発者は配列またはオブジェクトをキー値ストアとして使用するかどうかを選択できるようになりました。個人的には、オブジェクトと配列が提供する「エンティティ」と「コレクション」の構文上の違いが好きなので、WordPressのアプローチを好みます。


5

私の質問は、なぜ彼ら(Wordpress)が配列の代わりにオブジェクトを使用するのですか?

それは本当に良い質問であり、答えるのは簡単ではありません。WordpressstdClassでは、デフォルトでレコードをstdClassオブジェクトとして返すデータベースクラスを使用しているため、オブジェクトを使用するのが一般的であると推測できます。彼らはそれに慣れました(8年以上)そしてそれだけです。単純な事実の背後には、これ以上の考えはないと思います。

連想配列のための糖衣構文 -ゼーブ・スラスキー 標準オブジェクトに関するPHP以来3

  • stdClassオブジェクトは実際には配列よりも優れているわけではありません。それらはほとんど同じです。これは、言語の歴史的な理由によるものであり、stdClassオブジェクトは実際には制限されており、実際には非常に基本的な意味での一種の値オブジェクトにすぎません。
  • stdClassオブジェクトは、配列がエントリごとに行うように、メンバーの値を格納します。以上です。
  • PHPフリークだけstdClassがプライベートメンバーでオブジェクトを作成できます。そうすることには、もしあるとしても、あまりメリットはありません。
  • stdClassオブジェクトにはメソッド/関数はありません。したがって、Wordpressではそれを使用しません。
  • と比較しarrayて、リストまたは半構造化データを処理するのに役立つ関数ははるかに少なくなります。

ただし、配列に慣れている場合は、次のようにキャストしてください。

$array = (array) $object;

また、以前はオブジェクトであったデータに配列としてアクセスできます。またはあなたはそれを逆に好きです:

$object = (object) $array;

これは、番号などの無効なメンバー名のみを削除します。少し注意してください。しかし、全体像を把握できると思いますstdClass。の配列とオブジェクトに関する限り、大きな違いはありません。

関連:


4
  1. コードはそのようにクールに見えます
  2. オブジェクトは参照渡し
  3. オブジェクトは配列よりも強く型付けされているため、エラーが発生しやすくなります(または、存在しないメンバーを使用しようとすると、意味のあるエラーメッセージが表示されます)。
  4. 今日のすべてのIDEはオートコンプリートを備えているため、定義されたオブジェクトを操作する場合、IDEは多くのことを実行し、処理を高速化します。
  5. ロジックデータを同じボックスに簡単にカプセル化します。配列では、データを配列に格納し、さまざまな関数のセットを使用して処理します。
  6. 継承、機能がほとんどないが類似していない類似の配列がある場合、オブジェクトを使用して実行する場合よりも多くのコードを複製する必要があります

おそらく私が考えたもう少しの理由


「#オブジェクトは参照によって渡されます」:それは間違っています。オブジェクトはPHP変数参照として渡されません。彼らは決してしませんでした。
hakre 2011

@ hakre-php4を使用していますか?またはあなたが何を意味するか詳しく説明してください。
Itay Moav -Malimovka 2011

最近までワードプレスがPHP4でなかったわけではありませんが、PHP4またはPHP5では、オブジェクトは参照として渡されません。「よく言及されるPHP5 OOPのキーポイントの1つは、「オブジェクトはデフォルトで参照によって渡される」ということです。 。これは完全に真実ではありません。このセクションでは、いくつかの例を使用して、その一般的な考え方を修正します。」 オブジェクトと参照
hakre 2011

@ hakre-意味はわかりますが、すべての目的で、言語は参照のみを渡すかのように動作します。
Itay Moav -Malimovka

4

オブジェクトは、配列よりもはるかに強力です。クラスのインスタンスとしての各オブジェクトには、関数をアタッチできます。処理が必要なデータがある場合は、処理を行う関数が必要です。配列を使用すると、その配列でその関数を呼び出す必要があるため、ロジックを自分でデータに関連付ける必要があります。オブジェクトを使用すると、この関連付けはすでに行われているので、もう気にする必要はありません。

また、情報隠蔽のオブジェクト指向の原則を考慮する必要があります。データベースから出入りするすべてのものに直接アクセスできる必要はありません。


Wordpressはクラスのオブジェクトを返しますStdClass。これらのオブジェクトには、強調表示する内容に共通するものは何もありません。たとえば、それらには機能がなく、継承もありません。また、Wordpressの場合、すべてのクラス変数はパブリックです。
hakre 2011

はい、そうです。この場合、他の人が述べたように、それはあなたが好むものに依存していると思います。私はワードプレスには興味がありませんが、おそらくすべてのデータベース呼び出しをカプセル化しているため、戻るための特別なクラスを提供することはできません。しかし、私の答えは一般的であり、同様の考慮がメーカーによってなされたと思います...または彼らはただコインを投げました。
2011

彼らはstdClass、ca以来デフォルトでオブジェクトを返すデータベースヘルパークラスを使用するだけです。8年。配列を取得する場合は、オプションのパラメーターを設定して取得する必要があります。
hakre 2011

3

オブジェクトを返す理由はいくつかあります。

  1. 書き込みに$myObject->property必要な「オーバーヘッド」文字は、$myArray['element']

  2. オブジェクトはデータと機能を返すことができます。配列にはデータのみを含めることができます。

  3. 連鎖を有効にする: $myobject->getData()->parseData()->toXML();

  4. より簡単なコーディング:IDEオートコンプリートは、オブジェクトのメソッドとプロパティのヒントを提供できます。

パフォーマンスの観点から、配列はオブジェクトよりも高速であることがよくあります。パフォーマンスに加えて、アレイを使用する理由はいくつかあります。

  1. array _ *()ファミリーの関数によって提供される機能により、場合によっては必要なコーディングの量を減らすことができます。

  2. count()やforeach()などの操作は配列で実行できます。オブジェクトはこれを提供しません(IteratorまたはCountableを実装していない限り)。


2

通常、パフォーマンス上の理由で発生することはありません。通常、オブジェクトは配列よりもコストがかかります。

多くのAPIの場合、ストレージメカニズムであるだけでなく、他の機能を提供するオブジェクトと関係がある可能性があります。それ以外の場合、それは好みの問題であり、オブジェクトと配列を返すことには実際には利点がありません。


PHP5では、配列とオブジェクトのパフォーマンスの違いはごくわずかです。
ジャスティンᚅᚔᚈᚄᚒᚔ2011

2

配列は単なる値のインデックスです。一方、オブジェクトには、結果を生成できるメソッドが含まれています。もちろん、オブジェクトの値に直接アクセスできる場合もありますが、「正しい方法」は、オブジェクトのメソッド(そのオブジェクトの値を操作する関数)にアクセスすることです。

$obj = new MyObject;
$obj->getName();   // this calls a method (function), so it can decide what to return based on conditions or other criteria

$array['name'];   // this is just the string "name". there is no logic to it. 

オブジェクト変数に直接アクセスしている場合があります。これは通常は嫌われますが、それでもかなり頻繁に発生します。

$obj->name;   // accessing the string "name" ... not really different from an array in this case.

ただし、MyObjectクラスには「name」という変数がなく、代わりにfirst_name変数とlast_name変数があることを考慮してください。

$obj->getName();  // this would return first_name and last_name joined.
$obj->name;  // would fail...
$obj->first_name; 
$obj->last_name; // would be accessing the variables of that object directly.

これは非常に単純な例ですが、これがどこに向かっているのかがわかります。クラスは、変数のコレクションと、それらの変数をすべて自己完結型の論理エンティティ内で操作できる関数を提供します。そのエンティティのインスタンスはオブジェクトと呼ばれ、配列にはない論理的および動的な結果をもたらします。


1

ほとんどの場合、オブジェクトは配列と同じくらい高速ですが、PHPでは目立った違いはありません。主な理由は、オブジェクトが配列よりも強力であるということです。オブジェクト指向プログラミングを使用すると、オブジェクトを作成してデータだけでなく機能を格納できます。たとえば、PHPでは、MySQLiクラスを使用すると、手続き型アプローチではなく、組み込み関数のホストを使用して操作できるデータベースオブジェクトを作成できます。

したがって、主な理由は、OOPが優れたパラダイムであるということです。OOPを使用することが良いアイデアである理由についての記事を書きました。その概念を説明するには、http//tomsbigbox.com/an-introduction-to-oop/を参照してください。

マイナープラスとして、オブジェクトからデータを取得するために入力する量も少なくなります。$ test-> dataは$ test ['data']よりも優れています。


1

私はワードプレスに慣れていません。ここでの多くの答えは、オブジェクトの強みは関数型コードを含む能力があることを示唆しています。関数/ API呼び出しからオブジェクトを返す場合、ユーティリティ関数を含めることはできません。ただのプロパティ。

オブジェクトを返すことの強みは、APIの背後にあるものはすべて、コードを壊すことなく変更できることです。

例:キーと値のペアを持つデータの配列を取得します。キーはDB列を表します。DB列の名前が変更されると、コードが壊れます。


1

私はphp5.3.10(windows)で次のテストを実行しています:

for ($i = 0; $i < 1000000; $i++) {
    $x = array();
    $x['a'] = 'a';
    $x['b'] = 'b';
}

そして

for ($i = 0; $i < 1000000; $i++) {
    $x = new stdClass;
    $x->a = 'a';
    $x->b = 'b';
}

からコピー http://atomized.org/2009/02/really-damn-slow-a-look-at-php-objects/comment-page-1/#comment-186961

10人の同時ユーザーと10回(平均を取得するため)の関数を呼び出してから

  • 配列:100%
  • オブジェクト:214%– 216%(2倍遅い)。

別名、オブジェクトそれはまだ痛い遅いです。OOPは物事を整頓しますが、慎重に使用する必要があります。

Wordpressは何を適用していますか?どちらのソリューションも、オブジェクト、配列、オブジェクトと配列を使用しています。クラスwpdb後者を使用します(これがWordpressの心臓部です)。


PHP5.4での比較が表示されます。オブジェクトのパフォーマンスは卓越しており、配列よりも高速な場合もあります。
Sanket Sahu 2012

0

これは、OOPのボックス化とボックス化解除の原則に従います。JavaやC#などの言語はこれをネイティブにサポートしていますが、PHPはサポートしていません。ただし、言語自体にはそれをサポートする構造がないため、PHPではある程度達成できますが、雄弁ではありません。PHPにボックス型があると、連鎖に役立ち、すべてのオブジェクト指向を維持し、メソッドシグネチャで型のヒントを得ることができます。欠点はオーバーヘッドであり、「instanceof」構造を使用して実行する追加のチェックがあるという事実です。PDTのようなインテリセンスまたはコードアシストを備えた開発ツールを使用する場合は、型システムを持つこともプラスになります。メソッドをgoogle / bing / yahooする必要はなく、オブジェクト上に存在し、ツールを使用してドロップダウンを提供できます。


0

オブジェクトが単なるデータではないという点は、通常はデータと動作であるため有効ですが 、MartinFowlerの「PatternsofEnterprise Application Architecture」には、転送するこのタイプのシナリオに適用されるパターンが少なくとも1つあります。 1つのシステム(APIの背後にあるアプリケーション)と別のシステム(アプリケーション)からのデータ。

そのデータ転送オブジェクト-メソッド呼び出しの数を減らすためにプロセス間でデータを運ぶオブジェクト。

したがって、APIがDTOを返すか配列を返すかが問題である場合、パフォーマンスコストがごくわずかであれば、DTOオプションであると私が主張する、より保守しやすいオプションを選択する必要があります...しかしもちろんあなたもシステムを開発しているチームのスキルと文化、および各オプションの言語またはIDEサポートを考慮する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.