cách thực hành tốt nhất để khởi tạo các thành viên lớp trong php


10

Tôi có rất nhiều mã như thế này trong các hàm tạo của mình: -

function __construct($params) {

    $this->property = isset($params['property']) ? $params['property'] : default_val;

}

Có phải tốt hơn để làm điều này hơn là chỉ định giá trị mặc định trong định nghĩa thuộc tính? tức là public $property = default_val? Đôi khi có logic cho giá trị mặc định và một số giá trị mặc định được lấy từ các thuộc tính khác, đó là lý do tại sao tôi thực hiện điều này trong hàm tạo.

Tôi có nên sử dụng setters để tất cả logic cho các giá trị mặc định được tách ra không?

Câu trả lời:


8

Tôi đã có loại tranh luận triết học với bản thân mình trước đây. Đây là nơi tôi đứng hầu hết thời gian mặc dù tôi nhận ra đây là một câu trả lời dựa trên ý kiến:

Một điều tôi thấy có thể giúp trả lời câu hỏi là việc chuyển $ params có thể có hoặc không có các thuộc tính / thành viên mảng được đặt.

Trong những năm qua, tôi đã đi đến kết luận này:

Tránh việc vượt qua các mảng.

Tại sao? Chà, không có cách nào để đặt hoặc có các giá trị sentinel được xác định cho các đối số được truyền tùy chọn.

Nói cách khác, với mã bạn đã chỉ định, bạn không thể làm một cái gì đó như thế này:

function __construct($arg1 = NULL, $arg2 = DEFAULT_VAL) {

    $this->arg1 = $arg1;

    $this->arg2 = $arg2;

}

$ arg1 và $ arg2 là các đối số tùy chọn - nếu không được thông qua, chúng có NULL và DEFAULT_VAL tương ứng - không cần kiểm tra rõ ràng.

Có lẽ điều này có vẻ như tùy tiện.

Tôi nghĩ rằng tôi có được những gì bạn đang cố gắng thực hiện - việc chuyển một tham chiếu duy nhất trái ngược với hàng tấn tranh luận. Điều này đưa tôi đến sự loại trừ tiếp theo của tôi:

Nếu không chuyển các biến "nguyên tử" (chuỗi, số nguyên, bằng chữ) thì truyền đối tượng.

Có những lợi ích về hiệu năng ở đây vì việc truyền các đối tượng được thực hiện bằng cách tham chiếu (mặc dù các mảng tôi nghĩ là gần giống nhau trong PHP).

Vì vậy, bạn có thể làm một cái gì đó như:

function __construct(MyAwesomeObject $oArg) {

        $this->oArg = $oArg;

    }

Đối số được thông qua sau đó sẽ được đảm bảo có "property1", "property2" mặc dù có thể với chính các giá trị mặc định.

Ngoài ra, ở đây bạn có thể nhập gợi ý và một IDE tốt cũng sẽ tự động hoàn thành mã tự động.

Nhưng chúng tôi nhanh chóng nhận ra rằng chúng tôi có một con gà và một điều trứng đang diễn ra: bạn đang xây dựng một đối tượng với các đối số được truyền mà bản thân cần xây dựng tại một số điểm.

Vậy thứ này bỏ chúng ta ở đâu? Chà, tôi đã đi đến kết luận rằng cuối cùng tất cả các lớp chưng cất, vì thiếu một thuật ngữ tốt hơn, các biến "nguyên tử" (chuỗi, số float, double, ints, tài nguyên mà bạn có được điểm của tôi) và tôi có xu hướng thử để xây dựng tất cả các lớp với các kiểu hoặc đối tượng biến đó - nhưng không phải là mảng.

Vì vậy, tôi đã trả lời câu hỏi của bạn? có lẽ không chính xác Nhưng tôi hy vọng tôi đã minh họa một cái gì đó hữu ích mặc dù hơi phong cách. Tôi nghĩ rằng mã này sạch hơn một chút, dễ đọc hơn và ít tốn kém hơn.

Bây giờ, điều này không có nghĩa là bạn không nên vệ sinh đầu vào của mình. Đó là một cuộc thảo luận hoàn toàn khác.

Hi vọng điêu nay co ich.


1
Đó là một điểm tốt và rất tiện dụng cho các lời nhắc IDE nhưng có quá nhiều thuộc tính đối tượng để chuyển tất cả chúng dưới dạng tham số. Nếu bạn có 7 đối số cho biết 5 trong số đó là tùy chọn, bạn sẽ kết thúc với những thứ như thế new object($param1,-some default value so I can specify the next parameter-, $param3);và do đó, bạn có các giá trị mặc định được mã hóa cứng ở một số nơi khác nhau
rgvcorley

3

Mặc dù tôi có xu hướng tránh truyền mảng cho hàm tạo, đôi khi tôi thấy cần phải xử lý giá trị mảng đến (chẳng hạn như đối với một lớp đọc giá trị từ tệp cấu hình).

Trong trường hợp như thế này, tôi sẽ tận dụng các hàm mảng của PHP để đảm bảo rằng tôi đang làm việc với chính xác những gì tôi nghĩ tôi đang làm việc với:

public function import( array $incoming )
{
  $defaults = array(
      'foo' => DEFAULT_FOO
    , 'bar' => DEFAULT_BAR
    ...
  );

  $values = array_merge($defaults, array_intersect_key($incoming, $defaults));

  ...
}

Dòng cuối cùng đó sử dụng array_merge()để ghi đè bất kỳ giá trị nào $defaultsbằng các giá trị tương ứng của chúng từ đó $incoming. Tôi cũng sử dụng array_intersect_key()để đảm bảo rằng mảng kết quả không chứa bất kỳ khóa bổ sung nào mà lớp / phương thức sẽ không biết cách xử lý.


Xin chào, hành vi nào nếu $ mặc định chứa một mảng thay vì các biến đơn giản?
Pol Dellaiera

@PolDellaiera Nhìn vào array_merge_recursive.
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.