Tại sao trả về đối tượng thay vì mảng?


84

Tôi làm rất nhiều việc trong WordPress và tôi nhận thấy rằng nhiều hàm trả về đối tượng hơn là mảng. Kết quả cơ sở dữ liệu được trả về dưới dạng đối tượng trừ khi bạn yêu cầu cụ thể một mảng. Các lỗi được trả về dưới dạng đối tượng. Bên ngoài WordPress, hầu hết các API cung cấp cho bạn một đối tượng thay vì một mảng.

Câu hỏi của tôi là, tại sao họ sử dụng các đối tượng thay vì mảng? Đối với hầu hết các phần, điều đó không quá quan trọng, nhưng trong một số trường hợp, tôi thấy các vật thể khó hơn không chỉ xử lý mà còn quấn quanh đầu tôi. Có lý do hiệu suất cho việc sử dụng một đối tượng không?

Tôi là một lập trình viên PHP tự học. Tôi đã có bằng nghệ thuật tự do. Vì vậy, hãy tha thứ cho tôi nếu tôi thiếu một khía cạnh cơ bản của khoa học máy tính. ;)


5
Tôi tò mò về điều này liên quan đến nhược điểm của các đối tượng, như không thể sử dụng count()hoặc các array_*()chức năng trên chúng (ít nhất là liên quan đến việc lưu trữ / trả về dữ liệu khóa => giá trị). Dường như không ai đề cập đến nó, hoặc tôi đang thiếu một cái gì đó?
Wesley Murch

8
Các đối tượng có thể được thực hiện có thể đếm được và có thể lặp lại bằng cách triển khai các giao diện Countable hoặc Iterator. Kiểm tra php.net/manual/en/book.spl.php .
simshaun

Nếu đã cài đặt SPL và bạn triển khai giao diện có thể đếm được cho lớp đối tượng của mình thì bạn có thể gọi count()một đối tượng.
Không ai di chuyển ra khỏi SE

2
Trong nhiều trường hợp, một mảng thậm chí không có ý nghĩa vì bạn không trả về một tập hợp các đối tượng hoặc một loại tập hợp không dễ dàng mô phỏng với mảng. Khi bạn chỉ có một chuỗi các giá trị khác và không có ngữ nghĩa bổ sung nào được liên kết, thì vì Chúa hãy trả về một mảng - nhưng bạn sẽ thấy rằng điều đó hiếm khi xảy ra.

8
@delnan và những người khác: Xin lưu ý rằng @Dennis đang nói về mảng kết hợp , (còn gọi là. Từ điển, hay còn gọi là. Bản đồ), không phải mảng bình thường (chỉ số nguyên). Đây là một tính năng cốt lõi của PHP và phục vụ ít nhiều cùng mục đích với các lớp động ( stdClass). Tôi không chắc rằng câu hỏi này có một câu trả lời khác hơn là "Bởi vì lập trình viên làm việc chủ yếu trong OOP thích ngữ nghĩa của việc sử dụng các đối tượng"
BlueRaja - Danny Pflughoeft

Câu trả lời:


62

Đây là những lý do tại sao tôi thích các đối tượng nói chung:

  • Các đối tượng không chỉ chứa dữ liệu mà còn cả chức năng.
  • Đối tượng có (trong hầu hết các trường hợp) một cấu trúc được xác định trước. Điều này rất hữu ích cho thiết kế API. Hơn nữa, bạn có thể đặt các thuộc tính là công khai, được bảo vệ hoặc riêng tư.
  • đối tượng phù hợp hơn với phát triển hướng đối tượng.
  • Trong hầu hết các IDE tự động hoàn thành chỉ hoạt động cho các đối tượng.

Đây là một cái gì đó để đọc:


3
liên kết đầu tiên có vẻ là không tốt? Ý tôi là nó hoạt động, nhưng sẽ chuyển sang một khía cạnh khác
Geo

24

Đây có lẽ không phải là thứ bạn sẽ hiểu sâu cho đến khi bạn đã làm việc trong một dự án phần mềm lớn trong vài năm. Nhiều chuyên ngành khoa học máy tính mới sẽ cung cấp cho bạn câu trả lời với tất cả các từ phù hợp (đóng gói, chức năng với dữ liệu và khả năng bảo trì) nhưng ít người thực sự hiểu tại sao tất cả những thứ đó lại tốt.

Hãy xem qua một vài ví dụ.

  • Nếu các mảng được trả về, thì tất cả các giá trị cần được tính toán trước hoặc nhiều giá trị nhỏ cần được trả về mà bạn có thể xây dựng các giá trị phức tạp hơn từ đó.

Hãy nghĩ về một phương thức API trả về danh sách các bài đăng trên WordPress. Các bài viết này đều có tác giả, tác giả có tên, địa chỉ e-mail, thậm chí có thể là lý lịch kèm theo tiểu sử của họ.

Nếu bạn đang trả lại tất cả các bài đăng trong một mảng, bạn sẽ phải tự giới hạn mình trong việc trả về một mảng ID bài đăng:

[233, 41, 204, 111]

hoặc trả về một mảng lớn trông giống như sau:

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

Trường hợp đầu tiên trả về danh sách các ID không hữu ích lắm đối với bạn vì sau đó bạn cần thực hiện lệnh gọi API cho từng ID để nhận một số thông tin về bài đăng đó.

Trường hợp thứ hai sẽ kéo nhiều thông tin hơn bạn cần 90% thời gian và làm nhiều công việc hơn (đặc biệt nếu bất kỳ trường nào trong số đó rất phức tạp để xây dựng).

Mặt khác, một đối tượng có thể cung cấp cho bạn quyền truy cập vào tất cả thông tin bạn cần, nhưng chưa thực sự lấy được thông tin đó. Việc xác định giá trị của các trường có thể được thực hiện một cách lười biếng (nghĩa là khi giá trị là cần thiết chứ không phải trước) khi sử dụng một đối tượng.

  • Mảng hiển thị nhiều dữ liệu và khả năng hơn dự định

Quay lại ví dụ về mảng lớn được trả về. Bây giờ ai đó có thể xây dựng một ứng dụng lặp lại từng giá trị bên trong mảng bài đăng và in nó. Nếu API được cập nhật để chỉ thêm một phần tử bổ sung vào mảng bài đăng đó thì mã ứng dụng sẽ bị hỏng vì nó sẽ in một số trường mới mà có lẽ không nên. Nếu thứ tự của các mục trong mảng bài đăng mà API trả về thay đổi, điều đó cũng sẽ phá vỡ mã ứng dụng. Vì vậy, việc trả về một mảng sẽ tạo ra tất cả các loại phụ thuộc có thể có mà một đối tượng sẽ không tạo ra.

  • Chức năng

Một đối tượng có thể chứa thông tin bên trong nó sẽ cho phép nó cung cấp chức năng hữu ích cho bạn. Ví dụ, một đối tượng bài đăng có thể đủ thông minh để trả về các bài đăng trước đó hoặc tiếp theo. Một mảng không thể làm điều đó cho bạn.

  • Uyển chuyển

Tất cả những lợi ích của các đối tượng nêu trên giúp tạo ra một hệ thống linh hoạt hơn.


10

Câu hỏi của tôi là, tại sao họ sử dụng các đối tượng thay vì các mảng?

Có thể là hai lý do:

  • WordPress khá cũ
  • mảng nhanh hơn và chiếm ít bộ nhớ hơn trong hầu hết các trường hợp
  • dễ dàng hơn để xuất bản

Có lý do hiệu suất cho việc sử dụng một đối tượng không?

Không. Nhưng rất nhiều lý do tốt khác, ví dụ:

  • bạn có thể lưu trữ logic trong các đối tượng (phương thức, bao đóng, v.v.)
  • bạn có thể buộc cấu trúc đối tượng bằng giao diện
  • tự động hoàn thành tốt hơn trong IDE
  • bạn không nhận được thông báo cho các khóa mảng không xác định
  • cuối cùng, bạn có thể dễ dàng chuyển đổi bất kỳ đối tượng nào thành mảng

OOP ! = AOP :)

(Ví dụ, trong Ruby, mọi thứ đều là một đối tượng. Trước đây PHP là ngôn ngữ thủ tục / kịch bản.)


7

WordPress (và một số lượng lớn các ứng dụng PHP khác) sử dụng các đối tượng thay vì mảng, vì lý do khái niệm, thay vì kỹ thuật.

Một đối tượng (ngay cả khi chỉ là một thể hiện của stdClass) là một đại diện của một thứ. Trong WordPress, đó có thể là một bài đăng, một bình luận hoặc một người dùng. Mặt khác, một mảng là một tập hợp nhiều thứ. (Ví dụ: danh sách các bài đăng.)

Về mặt lịch sử, PHP không có sự hỗ trợ đối tượng tốt nên các mảng đã trở nên khá mạnh từ rất sớm. (Ví dụ: khả năng có các khóa tùy ý thay vì chỉ được lập chỉ mục bằng 0.) Với hỗ trợ đối tượng có sẵn trong PHP 5, các nhà phát triển hiện có lựa chọn giữa việc sử dụng mảng hoặc đối tượng làm kho lưu trữ khóa-giá trị. Cá nhân tôi thích cách tiếp cận WordPress hơn vì tôi thích sự khác biệt về cú pháp giữa 'thực thể' và 'tập hợp' mà các đối tượng và mảng cung cấp.


5

Câu hỏi của tôi là, tại sao họ (Wordpress) sử dụng các đối tượng thay vì mảng?

Đó thực sự là một câu hỏi hay và không dễ trả lời. Tôi chỉ có thể giả định rằng việc sử dụng stdClasscác đối tượng trong Wordpress là phổ biến vì chúng đang sử dụng một lớp cơ sở dữ liệu theo mặc định trả về các bản ghi dưới dạng một stdClassđối tượng. Họ đã quen với nó (8 năm và hơn thế nữa) và thế là xong. Tôi không nghĩ rằng có nhiều suy nghĩ đằng sau thực tế đơn giản.

cú pháp đường cho mảng kết hợp - Zeev Suraski về đối tượng chuẩn kể từ PHP 3

  • stdClasscác đối tượng không thực sự tốt hơn mảng. Chúng khá giống nhau. Đó là vì một số lý do lịch sử của ngôn ngữ cũng như stdClasscác đối tượng thực sự bị hạn chế và thực sự chỉ là một loại đối tượng có giá trị theo nghĩa rất cơ bản.
  • stdClasscác đối tượng lưu trữ các giá trị cho các thành viên của chúng giống như một mảng thực hiện cho mỗi mục nhập. Và đó là nó.
  • Chỉ những kẻ kỳ quặc trong PHP mới có thể tạo stdClasscác đối tượng với các thành viên riêng. Không có nhiều lợi ích - nếu có - làm như vậy.
  • stdClasscác đối tượng không có bất kỳ phương thức / chức năng nào. Vì vậy, không sử dụng điều đó trong Wordpress.
  • So với array, có ít chức năng hữu ích hơn để xử lý dữ liệu danh sách hoặc bán cấu trúc.

Tuy nhiên, nếu bạn đã quen với mảng, chỉ cần truyền:

$array = (array) $object;

Và bạn có thể truy cập dữ liệu trước đây là một đối tượng, dưới dạng một mảng. Hoặc bạn thích nó theo cách khác:

$object = (object) $array;

Điều này sẽ chỉ loại bỏ các tên thành viên không hợp lệ, như số. Vì vậy, hãy cẩn thận một chút. Nhưng tôi nghĩ rằng bạn sẽ có được bức tranh toàn cảnh: Không có nhiều sự khác biệt miễn là về mảng và đối tượng stdClass.

Có liên quan:


4
  1. Mã trông ngầu hơn theo cách đó
  2. Đối tượng chuyển qua tham chiếu
  3. Các đối tượng được gõ mạnh hơn sau đó là mảng, do đó dẫn đến lỗi (hoặc cung cấp cho bạn một thông báo lỗi có ý nghĩa khi bạn cố gắng sử dụng thành viên chưa tồn tại)
  4. Tất cả các IDE ngày nay đều có tính năng tự động hoàn thành, vì vậy khi làm việc với các đối tượng đã xác định, IDE sẽ giúp bạn rất nhiều và tăng tốc mọi thứ
  5. Dễ dàng đóng gói logic dữ liệu trong cùng một hộp, trong đó với mảng, bạn lưu trữ dữ liệu trong mảng, sau đó sử dụng một tập hợp các hàm khác nhau để xử lý nó.
  6. Kế thừa, Nếu bạn có một mảng tương tự với chức năng gần như nhưng không tương tự, bạn sẽ phải sao chép nhiều mã hơn thì nếu bạn làm điều đó với các đối tượng

Có lẽ một số lý do tôi đã nghĩ đến


"# Objects pass by reference": Sai rồi. Các đối tượng không được chuyển như một tham chiếu biến PHP. Họ không bao giờ làm vậy.
hakre

@hakre - bạn đang sử dụng php4? hoặc vui lòng giải thích ý bạn.
Itay Moav -Malimovka

Không phải là wordpress không phải là PHP 4 cho đến gần đây nhưng trong PHP 4 hoặc PHP 5, các đối tượng không được truyền dưới dạng tham chiếu: "Một trong những điểm quan trọng của PHP5 OOP thường được đề cập là" các đối tượng được truyền theo tham chiếu theo mặc định " . Điều này không hoàn toàn đúng. Phần này điều chỉnh lại suy nghĩ chung đó bằng một số ví dụ. " Đối tượng và tài liệu tham khảo
hakre

@hakre - Tôi hiểu ý bạn, nhưng đối với mọi mục đích, ngôn ngữ hoạt động như thể bạn chỉ chuyển tham chiếu.
Itay Moav -Malimovka

4

Các đối tượng mạnh hơn nhiều so với các mảng. Mỗi đối tượng như một thể hiện của một lớp có thể có các hàm được đính kèm. Nếu bạn có dữ liệu cần xử lý thì bạn cần một hàm thực hiện xử lý. Với một mảng, bạn sẽ phải gọi hàm đó trên mảng đó và do đó tự liên kết logic với dữ liệu. Với một đối tượng, sự liên kết này đã được thực hiện và bạn không cần phải quan tâm đến nó nữa.

Ngoài ra, bạn nên xem xét nguyên tắc giấu thông tin của OO. Không phải mọi thứ quay lại hoặc đi đến cơ sở dữ liệu đều có thể truy cập trực tiếp được.


Wordpress trả về các đối tượng của lớp StdClass. Những đối tượng đó không có điểm chung nào với những gì bạn làm nổi bật. Ví dụ, chúng không có chức năng và chúng không có tính kế thừa. Và trong trường hợp của Wordpress, tất cả các biến lớp là công khai.
hakre

Đúng là như vậy. Tôi nghĩ trong trường hợp này, như những người khác đã nói, chỉ tùy thuộc vào những gì bạn thích. Tôi không thích wordpress nhưng có lẽ họ đóng gói tất cả các lệnh gọi cơ sở dữ liệu và do đó không thể cung cấp bất kỳ lớp chuyên biệt nào để trả về. Nhưng câu trả lời của tôi nói chung là và tôi nghĩ rằng các nhà sản xuất đã cân nhắc tương tự ... Hoặc họ chỉ ném một đồng xu.
Không ai di chuyển ra khỏi SE

Họ chỉ sử dụng một lớp trợ giúp cơ sở dữ liệu trả về stdClasscác đối tượng theo mặc định kể từ ca. 8 năm. Nếu bạn muốn lấy một mảng, bạn cần đặt một tham số tùy chọn để lấy nó.
hakre

3

Có một số lý do để trả về các đối tượng:

  1. Viết $myObject->propertyyêu cầu ít ký tự "overhead" hơn$myArray['element']

  2. Đối tượng có thể trả về dữ liệu và chức năng; mảng chỉ có thể chứa dữ liệu.

  3. Bật chuỗi: $myobject->getData()->parseData()->toXML();

  4. Mã hóa dễ dàng hơn: Tự động hoàn thành IDE có thể cung cấp gợi ý về phương pháp và thuộc tính cho đối tượng.

Về hiệu suất, mảng thường nhanh hơn đối tượng. Ngoài hiệu suất, có một số lý do để sử dụng mảng:

  1. Chức năng được cung cấp bởi họ hàm mảng _ * () có thể làm giảm số lượng mã hóa cần thiết trong một số trường hợp.

  2. Các phép toán như count () và foreach () có thể được thực hiện trên mảng. Các đối tượng không cung cấp điều này (trừ khi chúng triển khai Iterator hoặc Countable ).


2

Nó thường không phải vì lý do hiệu suất. Thông thường, các đối tượng có giá cao hơn các mảng.

Đối với nhiều API, nó có thể liên quan đến các đối tượng cung cấp chức năng khác ngoài việc là một cơ chế lưu trữ. Nếu không, đó là một vấn đề ưu tiên và thực sự không có lợi ích gì khi trả về một đối tượng so với một mảng.


Trong PHP5, sự khác biệt về hiệu suất giữa các mảng và các đối tượng là không đáng kể.
Justin ᚅᚔᚈᚄᚒᚔ

2

Một mảng chỉ là một chỉ mục của các giá trị. Trong khi một đối tượng chứa các phương thức có thể tạo ra kết quả cho bạn. Chắc chắn, đôi khi bạn có thể truy cập trực tiếp các giá trị của đối tượng, nhưng "cách đúng để làm điều đó" là truy cập vào các phương thức của đối tượng (một hàm hoạt động trên các giá trị của đối tượng đó).

$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. 

Đôi khi bạn đang truy cập trực tiếp vào một biến đối tượng, điều này thường khiến bạn khó chịu, nhưng nó vẫn xảy ra khá thường xuyên.

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

Tuy nhiên, hãy xem xét rằng lớp MyObject không có một biến được gọi là 'name', mà thay vào đó có một biến first_name và 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.

Đây là một ví dụ rất đơn giản, nhưng bạn có thể thấy điều này sẽ xảy ra. Một lớp cung cấp một tập hợp các biến và các hàm có thể hoạt động trên các biến đó, tất cả đều nằm trong một thực thể lôgic độc lập. Một thể hiện của thực thể đó được gọi là đối tượng và nó giới thiệu các kết quả logic và động, điều mà một mảng đơn giản là không có.


1

Hầu hết các đối tượng thời gian cũng nhanh như nhau, nếu không muốn nói là nhanh hơn mảng, trong PHP không có sự khác biệt đáng chú ý. lý do chính là các đối tượng mạnh hơn mảng. Lập trình hướng đối tượng cho phép bạn tạo các đối tượng và lưu trữ không chỉ dữ liệu, mà còn cả chức năng trong đó, ví dụ như trong PHP MySQLi Class cho phép bạn có một đối tượng cơ sở dữ liệu mà bạn có thể thao tác bằng cách sử dụng một loạt các hàm có sẵn, thay vì cách tiếp cận thủ tục.

Vì vậy, lý do chính là OOP là một mô hình tuyệt vời. Tôi đã viết một bài báo về lý do tại sao sử dụng OOP là một ý tưởng hay và giải thích khái niệm này, bạn có thể xem tại đây: http://tomsbigbox.com/an-introduction-to-oop/

Ngoài ra, bạn cũng phải gõ ít hơn để lấy dữ liệu từ một đối tượng - $ test-> data tốt hơn $ test ['data'].


1

Tôi không quen với cách bấm từ. Rất nhiều câu trả lời ở đây cho thấy điểm mạnh của các đối tượng là có khả năng chứa mã chức năng. Khi trả về một đối tượng từ một hàm / lệnh gọi API, nó không được chứa các hàm tiện ích. Chỉ là thuộc tính.

Điểm mạnh trong việc trả về các đối tượng là bất cứ thứ gì nằm sau API đều có thể thay đổi mà không làm hỏng mã của bạn.

Ví dụ: Bạn nhận được một mảng dữ liệu với các cặp khóa / giá trị, khóa đại diện cho cột DB. Nếu cột DB được đổi tên, mã của bạn sẽ bị hỏng.


1

Tôi đang chạy thử nghiệm tiếp theo trong php 5.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';
}

Được sao chép từ http://atomized.org/2009/02/really-damn-slow-a-look-at-php-objects/comment-page-1/#comment-186961

Gọi hàm cho 10 người dùng đồng thời và 10 lần (để lấy giá trị trung bình) thì

  • Mảng: 100%
  • Đối tượng: 214% - 216% (chậm hơn 2 lần).

AKA, Object nó vẫn còn chậm. OOP giữ mọi thứ ngăn nắp tuy nhiên nó nên được sử dụng cẩn thận.

Wordpress đang áp dụng những gì ?. Cả hai giải pháp đều sử dụng đối tượng, mảng và đối tượng & mảng, Class wpdb sử dụng sau này (và nó là trái tim của Wordpress).


Bạn sẽ thấy so sánh trên PHP 5.4. Hiệu suất của các đối tượng vượt trội và đôi khi còn nhanh hơn Mảng.
Sanket Sahu 23/10/12

0

Nó tuân theo nguyên tắc quyền anh và mở hộp của OOP. Trong khi các ngôn ngữ như Java và C # tự nhiên hỗ trợ điều này, PHP thì không. Tuy nhiên, nó có thể được thực hiện ở một mức độ nào đó trong PHP, chỉ là không hùng hồn vì bản thân ngôn ngữ này không có các cấu trúc hỗ trợ nó. Có các kiểu hộp trong PHP có thể giúp tạo chuỗi, giữ mọi thứ theo hướng đối tượng và cho phép gợi ý kiểu trong chữ ký phương thức. Nhược điểm là chi phí cao và thực tế là bây giờ bạn phải kiểm tra thêm bằng cách sử dụng cấu trúc â € œinstanceofâ €. Có một hệ thống kiểu cũng là một điểm cộng khi sử dụng các công cụ phát triển có intellisense hoặc hỗ trợ mã như PDT. Thay vì phải google / bing / yahoo để tìm phương thức, nó tồn tại trên đối tượng và bạn có thể sử dụng công cụ này để cung cấp danh sách thả xuống.


0

Mặc dù các điểm được đưa ra về các đối tượng không chỉ là dữ liệu là hợp lệ vì chúng thường là dữ liệu và hành vi nhưng có ít nhất một mẫu được đề cập trong "Các mẫu kiến ​​trúc ứng dụng doanh nghiệp" của Martin Fowler áp dụng cho loại cenario mà bạn đang chuyển giao dữ liệu từ một hệ thống (ứng dụng đằng sau API) và một hệ thống khác (ứng dụng của bạn).

Đối tượng truyền dữ liệu của nó - Một đối tượng mang dữ liệu giữa các quá trình để giảm số lượng các lệnh gọi phương thức.

Vì vậy, nếu câu hỏi là liệu các API nên trả về DTO hay một mảng, tôi sẽ nói rằng nếu chi phí hiệu suất là không đáng kể thì bạn nên chọn tùy chọn dễ bảo trì hơn mà tôi sẽ tranh luận là tùy chọn DTO ... nhưng tất nhiên bạn cũng phải xem xét các kỹ năng và văn hóa của nhóm đang phát triển hệ thống của bạn và ngôn ngữ hoặc hỗ trợ IDE cho mỗi tùy chọn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.