2009-11-29 32 views
13

Bắt đầu với phiên bản 5.3, PHP hỗ trợ late binding cho các phương pháp tĩnh. Mặc dù đây là một tính năng hữu ích nhưng chắc chắn chỉ có một vài trường hợp việc sử dụng nó thực sự cần thiết (ví dụ: mẫu Bản ghi hoạt động).Có thể sử dụng quá nhiều ràng buộc tĩnh muộn trong PHP không?

Hãy xem xét các ví dụ:

1. constructors Thuận tiện (::create())

class SimpleObject 
{ 
    public function __construct() { /* ... */ } 

    public static function create() 
    { 
     return new static; // or: return new self; 
    } 
} 

Nếu lớp này có thể kéo dài (tuy nhiên, nó không được gia hạn bởi bất kỳ lớp trong cùng một gói), nên liên kết tĩnh muộn được sử dụng chỉ để làm cho việc mở rộng dễ dàng hơn (mà không phải viết lại phương thức ::create(), và quan trọng hơn, mà không cần phải nhớ để làm điều đó)?

Lưu ý: thành ngữ này được sử dụng để làm việc xung quanh khả năng không thể gọi các phương thức trên đối tượng vừa được xây dựng: new SimpleObject()->doStuff() không hợp lệ trong PHP.


2. Lớp hằng

class TagMatcher 
{ 
    const TAG_PATTERN = '/\<([a-z\-]+?)\>/i'; 

    private $subject; 

    public function construct($subject) { $this->subject = $subject; } 

    public function getAllTags() 
    { 
     $pattern = static::TAG_PATTERN; 
     preg_match_all($pattern, $this->subject); 
     return $pattern[1]; 
    } 
} 

Lý do để sử dụng static:: trong ví dụ này là tương tự như trước đó. Nó được sử dụng chỉ vì lớp này có thể được thực hiện để phù hợp với các thẻ được tạo khác nhau chỉ bằng cách mở rộng nó và ghi đè hằng số.


Vì vậy, để kết thúc tất cả, những công dụng này (và những thứ tương tự) của liên kết tĩnh trễ có quá mức không? Có hiệu suất đáng chú ý nào không? Ngoài ra, không thường xuyên sử dụng các ràng buộc muộn làm giảm hiệu suất tổng thể tăng được đưa ra bởi bộ đệm opcode?

+0

Vâng, điều thứ hai có thể đạt được bằng cách ghi đè biến riêng và sử dụng '$ this', đúng không? Hay tôi hiểu nhầm điều gì đó? – Franz

+1

Có, nhưng tôi chỉ không thể đưa ra một ví dụ tốt hơn ... Có nó như là một 'const' có nghĩa là tránh sao chép nó thông qua tất cả các trường hợp. Và ngay cả khi copy-on-write của PHP sẽ tối ưu hóa điều này, nó chắc chắn sẽ tốt hơn như là một hằng số lớp, bởi vì nó thực sự là một giá trị không đổi toàn lớp. –

+0

... và tất cả điều đó, tôi thực sự có nghĩa rằng trong trường hợp này, sử dụng các biến mẫu trông giống như một giải pháp thay thế, trong khi 'static ::' thì không. –

Trả lời

13

Vì vậy, để quấn tất cả lên, những công dụng này (và những cái tương tự) của liên kết tĩnh muộn có phải là quá mức không? Có hiệu suất đáng chú ý nào không? Ngoài ra, không thường xuyên sử dụng các ràng buộc muộn làm giảm hiệu suất tổng thể tăng được đưa ra bởi bộ đệm opcode?

Việc giới thiệu sửa lỗi cố định cuối một lỗ hổng trong mô hình đối tượng của PHP. Nó không phải về hiệu suất, nó là về ngữ nghĩa.

Ví dụ: tôi muốn sử dụng các phương pháp tĩnh bất cứ khi nào việc triển khai phương pháp không sử dụng $this. Chỉ vì một phương thức là tĩnh không có nghĩa là bạn không muốn ghi đè nó đôi khi. Trước PHP 5.3, hành vi là không có lỗi nào bị gắn cờ nếu bạn overrode một phương thức tĩnh, nhưng PHP sẽ chỉ đi trước và âm thầm sử dụng phiên bản của cha mẹ. Ví dụ, mã bên dưới in 'A' trước PHP 5.3. Đó là hành vi bất ngờ cao.

Cố định cuối cố định nó, và bây giờ cùng mã in 'B'.

<?php 
class A { 
    public static function who() { 
    echo __CLASS__; 
    } 
    public static function test() { 
    static::who(); 
    } 
} 

class B extends A { 
    public static function who() { 
    echo __CLASS__; 
    } 
} 

B::test(); 
?> 
+0

Hãy bình luận sau khi downvote. – erenon

+11

Tôi biết đây là một chủ đề cũ, nhưng tìm thấy nó thông qua google. Mã ví dụ của bạn thực sự nên in 'A' bất kể phiên bản PHP. Để kích hoạt các ràng buộc tĩnh trễ, hãy sử dụng từ khóa tĩnh. VÍ DỤ.thay thế self :: who(); với static :: who(); và nó sẽ in 'B' – Maurice

3

phương pháp tĩnh (sớm hoặc trễ) tạo khớp nối chặt chẽ và (do đó) giảm khả năng kiểm tra. bạn có thể tạo các chương trình lớn trong PHP mà không cần sử dụng nhiều hơn một vài cuộc gọi tĩnh. đối với tôi, các phương thức tĩnh trễ là một tính năng không.

chỉnh sửa để trả lời câu hỏi của Marco Demaio, cách phương pháp tĩnh làm giảm khả năng kiểm tra?

Tôi xin lỗi nếu điều này hiển nhiên đối với bạn, các thành viên tĩnh (cả dữ liệu và phương pháp) hữu ích và không gây hại nếu sử dụng có trách nhiệm, tôi đã ám chỉ đến việc lạm dụng phổ biến.

nói rằng bạn có một ứng dụng web sử dụng cơ sở dữ liệu SQL. đối tượng kinh doanh của bạn có thể truy xuất dữ liệu bằng cách sử dụng giao diện tĩnh hoặc thông qua đa hình. hoặc

class MyBusinessObject 
extends... 
{ 
    public function doThisOrThat(...) 
    { 
    $results = db::query('sql string...'); 
    ... 
    } 
} 

hoặc

class MyBusinessObject 
extends... 
{ 
    public function __construct(dbconn $db) 
    { 
    $this->db = $db; 
    } 
    private $db; 
    public function doThisOrThat(...) 
    { 
    $results = $this->db->query('sql string...'); 
    ... 
    } 
} 

sau này là dễ dàng hơn để kiểm tra (như trong: tôi muốn kiểm tra xem chuỗi sql xây dựng từ nguyên liệu đầu vào như vậy như vậy-và-là như vậy-và-như vậy) vì việc tạo một triển khai giao diện dbconn dễ dàng hơn là thay đổi ý nghĩa của db::. tại sao bạn muốn?vì bạn không cần một cơ sở dữ liệu thực để kiểm tra hành vi soạn thảo sql và trên thực tế, việc thử nghiệm cho dễ dàng hơn mà không cần một cơ sở dữ liệu thực sự. Ngoài ra, nó dễ dàng hơn để tiêu diệt người tiêu dùng sql nếu các bài kiểm tra của bạn có liên quan với một khía cạnh khác của CUT (Code Under Test).

kiểm tra luôn ngụ ý nằm trong mã thử nghiệm về cộng tác viên của nó và tránh giao diện tĩnh ("doublecolon" hoặc "quadridot") có nghĩa là lời nói dối không phải là một phẫu thuật lớn. mã thử nghiệm là từ mã sản xuất, kết quả thử nghiệm ít có ý nghĩa hơn.

+0

+1 Vì tôi đã bắt đầu sử dụng các trường hợp trên các phương thức tĩnh, mọi thứ trở nên dễ dàng hơn rất nhiều xung quanh –

+0

@just somebody: ý của bạn là gì khi bạn nói các phương thức tĩnh tạo ra sự ghép nối chặt chẽ làm giảm khả năng test? Tôi không hiểu cách họ có thể giảm khả năng kiểm tra. –

+0

@Marco Demaio: xem câu trả lời đã chỉnh sửa. –

1

Nơi tôi tìm thấy nhu cầu sử dụng kết buộc tĩnh muộn là cho phép mô phỏng phương pháp tĩnh để kiểm tra đơn vị với PHPUnit. Vấn đề tôi có là tôi không thích thay đổi mã nghiêm ngặt để cho phép chế nhạo, nhưng tôi có thể vượt qua điều đó.

Để trả lời câu hỏi của bạn, tuy nhiên, tôi sẽ đặt cược rằng bất kỳ chi phí hiệu suất nào mang theo, nó sẽ nhợt nhạt so với hầu hết các thời gian chạy chương trình. Nói cách khác, nó sẽ không tạo ra sự khác biệt đáng chú ý.

Các vấn đề liên quan