Đây có phải là một nguyên tắc cơ bản, hoặc rất mong muốn, để có các phương thức lớp trả về cho $ $ này chứ không phải là một giá trị?


8

Tôi thực sự mới bắt đầu học OOP. Tôi đã bắt đầu khoảng một năm trước và đã viết khoảng 15.000 dòng của nó. Nhưng tôi đã viết tất cả mà hầu như không có kinh nghiệm nào khi nhìn vào OOP của người khác.

Hầu hết các hàm lớp của tôi trả về một giá trị hoặc thay đổi các thuộc tính của lớp và trả về true / false. Một số trong đó trả về một giá trị cũng lưu giá trị đó vào thuộc tính lớp (sau lần kiểm tra đầu tiên nếu thuộc tính lớp đã được đặt, có thể tránh được cuộc gọi cơ sở dữ liệu).

Bây giờ tôi đang đào rất nhiều trong Magento / Zend và tôi nhận thấy rất nhiều phương thức lớp của họ trả về "$ this". Theo tôi hiểu, không giống như trong các hàm thông thường, các phương thức lớp trả về $ hành động này bằng tham chiếu không theo giá trị, để bạn lấy lại chính đối tượng bạn đã bắt đầu thay vì một bản sao.

Là trả lại $thismột cái gì đó mà tôi nên làm nhiều hơn? Liệu nó làm cho mã dễ dàng hơn để duy trì và sử dụng? Là trả lại $thiscần thiết để chuỗi phương thức lớp?


12
Đây là một kỹ thuật được sử dụng để tạo Giao diện Thông thạo. Nếu Giao diện thông thạo không phải là mục tiêu của bạn, thì bạn không cần phải quay lại $this. vi.wikipedia.org/wiki/Fluent_interface
Robert Harvey

1
Bạn có thể muốn chỉ định PHP tại đây ...
Nathan C. Tresch

4
@Robert, bạn nên làm cho câu trả lời.
Karl Bielefeldt

Đây là một mẫu giao diện lưu loát trong PHP ( devzone.zend.com/777/fluent-interfaces-in-php )
OnesimusUnbound

2
Là phương pháp xích cần thiết? no();Có phải đôi khi chúng rất thuận tiện? yes().yes().yes().yes().yes();: D
Viliam Búr

Câu trả lời:


14

Đây là một kỹ thuật được sử dụng để tạo Giao diện Thông thạo. Nếu Giao diện thông thạo không phải là mục tiêu của bạn, thì bạn không cần phải trả lại $ này.

Giao diện lưu loát cho phép bạn viết mã trông như thế này (mã giả):

private void makeFluent(Customer customer) {
    customer.newOrder()
            .with(6, "TAL")
            .with(5, "HPK").skippable()
            .with(3, "LGV")
            .priorityRush();
}

Nó hoạt động, bởi vì mỗi cuộc gọi phương thức có quyền truy cập vào đối tượng ban đầu, nhờ vào việc gọi lại phương thức trước đó this. Đoạn mã trên ít nhiều tương đương với:

private void makeFluent(Customer customer) {
    var newOrder = customer.newOrder()
    newOrder.with(6, "TAL");
    newOrder.with(5, "HPK", skippable := true);
    newOrder.with(3, "LGV");
    newOrder.priorityRush();
    ...
}

thiskhông phải lúc nào cũng trở lại. Đôi khi một đối tượng khác được trả lại. Linq hoạt động như thế này, trả về một IEnumerable(đại diện lười biếng của một bộ sưu tập, một công cụ trạng thái được sửa đổi, về cơ bản) từ mỗi phương thức Linq trong chuỗi.

Nó đòi hỏi nhiều nỗ lực và suy nghĩ để tạo ra một giao diện trôi chảy hơn là chỉ đơn giản là thiết lập tất cả các tham số trong một hàm tạo. Bạn phải tìm hiểu xem đối tượng có mọi thứ cần thiết để có đầy đủ chức năng hay không và không phải lúc nào cũng rõ ràng chính xác phương thức đã cho là gì, hoặc theo thứ tự bạn cần gọi phương thức. Ví dụ:

20.minutes.ago

Có vẻ sạch sẽ, nhưng làm thế nào nó hoạt động, chính xác?

http://en.wikipedia.org/wiki/Fluent_interface
http://www.martinfowler.com/bliki/FluentInterface.html


2

Trả về $ this trả về một thể hiện của đối tượng mà phương thức là thành viên của. Có rất nhiều trường hợp bạn muốn làm điều này, nhưng cho đến khi bạn hiểu chính xác những gì tôi vừa nói và có thể xác định trường hợp sử dụng cho nó, bạn không thực sự cần nó.

Ví dụ về thời điểm sử dụng này:

Một btree là một ví dụ trong PHP về nơi bạn sẽ trả lại một đứa trẻ $ này, điều này không hoàn toàn giống như vậy nhưng tôi nghĩ nó có liên quan đến cuộc thảo luận này.

Viết hàm tạo của riêng bạn, bạn sẽ luôn trả về $ this

Để làm rõ về các tham chiếu, khi bạn trả về $, bạn đang gửi một tham chiếu đến đối tượng mà phương thức đang chạy là một phần của. Tôi nghĩ rằng các quy tắc của PHP khi nó hoạt động trên một tham chiếu so với một giá trị đôi khi không rõ ràng, nhưng trong trường hợp này $ này luôn luôn là một tham chiếu. Để rõ ràng: một tham chiếu luôn là 'ví dụ mà bạn đã có' và không bao giờ là bản sao, trong khi 'giá trị' là bản sao. Đây là hai loại ngữ nghĩa đối số


Tôi hiểu Returning $this returns an instance of the object that the method is a member of.Và trong PHP OOP tôi tin, như tôi đã nói trong câu hỏi của mình và bạn nói trong câu trả lời của bạn, rằng trường hợp mà nó trả về thực sự là một ví dụ giống như nó ... tức là nó trả về không phải là bản sao của chính nó mà là chính nó. Nếu tôi hiểu đúng.
Butussy Butkus

@BriptButkus Có, một tài liệu tham khảo luôn là 'ví dụ mà bạn đã có' và không bao giờ là bản sao, trong khi 'giá trị' là bản sao. Đây là hai loại ngữ nghĩa đối số.
Nathan C. Tresch

@BriptButkus Tôi đã sửa đổi câu trả lời của mình với thông tin đó
Nathan C. Tresch

1

"Tham chiếu PHP là một bí danh, cho phép hai biến khác nhau ghi vào cùng một giá trị. Kể từ PHP 5, một biến đối tượng không chứa chính đối tượng đó là giá trị nữa. Nó chỉ chứa một định danh đối tượng cho phép người truy cập đối tượng cho phép tìm đối tượng thực tế. Khi một đối tượng được gửi bằng đối số, được trả về hoặc được gán cho một biến khác, các biến khác nhau không phải là bí danh: chúng giữ một bản sao của mã định danh, trỏ đến cùng một đối tượng. "

Lợi thế thực sự để trả lại $ này là trong các mẫu thiết kế thành phần đối tượng, đặc biệt là trong Magento. Lấy ví dụ Mage_Core_Sales_Order_Invoice-> capt () trả về $ this. Phương pháp này trông giống như:

  public function capture()
    {
        $this->getOrder()->getPayment()->capture($this);
        if ($this->getIsPaid()) {
            $this->pay();
        }
        return $this;
    }

dòng:

$this->getOrder()->getPayment()->capture($this);

Truyền mô hình hóa đơn làm tài liệu tham khảo, rất hữu ích trong các mẫu thành phần đối tượng. Sự trở lại của $ này cũng là một tài liệu tham khảo. Vì vậy, phương thức gọi -> capt () trên mô hình hóa đơn có thể tiếp tục hoạt động với một cuộc gọi đối tượng được xâu chuỗi tiếp theo để dễ đọc mã theo ngữ cảnh.

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.