2013-05-04 14 views
9

Tôi không chắc chắn những gì tiêu đề nên được, nhưng mã nên giải thích nó tốt hơn:Tăng trên "__toString"

class Group { 
    private $number = 20; 

    public function __toString() { 
     return "$this->number"; 
    } 
} 

$number = new Group(); 
echo $number, PHP_EOL; 
echo ++ $number, PHP_EOL; 

echo PHP_EOL; 

$number = "20"; 
echo $number, PHP_EOL; 
echo ++ $number, PHP_EOL; 

echo PHP_EOL; 

$number = 20; 
echo $number, PHP_EOL; 
echo ++ $number, PHP_EOL; 

Output:

20 
20    <--- Expected 21 

20 
21 

20 
21 

Bất cứ ý tưởng tại sao tôi đã 20 thay vì 21? Thậm chí sau đó vào mã bên dưới hoạt động:

$i = null ; 
echo ++$i ; // output 1 

Tôi biết Group là một đối tượng mà thực hiện __toString, tôi mong đợi ++ để làm việc với các chuỗi từ __toString hoặc ít nhất throw an error

+0

PHP có cung cấp một cách để quá tải các nhà khai thác tăng? Vì lớp của bạn không dễ dàng chuyển đổi thành kiểu số, bạn có thể phải nói cho PHP biết bạn muốn ++ làm gì. – dlp

+1

nếu bạn khai báo số $ không riêng tư trong lớp Nhóm và sau đó thử echo ++ $ number-> number, PHP_EOL; công trinh? – LuckyStarr

+0

Nope .. nhưng đó là tăng trên chuỗi và thậm chí nếu không .. tôi sẽ nhận được một lỗi – Baba

Trả lời

12

Thứ tự mà các hoạt động xảy ra là điều quan trọng:

  1. Biến sẽ được lấy như một đối tượng, nó sẽ không được đúc thành một số nguyên (hay cái gì khác).

  2. Nhà điều hành ++ này tăng giá trị lval (giá trị dài) của zval, nhưng thường không có gì khác. Con trỏ đối tượng vẫn giữ nguyên. Các nội bộ (fast_)increment_function sẽ được gọi với zval trong đó có một con trỏ đến đối tượng, mà kiểm tra các loại đầu tiên. Nếu nó là một đối tượng, nó không làm gì cả. Vì vậy, khi zval của bạn là một đối tượng, nó là hữu ích như là một không hoạt động. Điều này sẽ không xuất hiện bất kỳ cảnh báo nào.

  3. Chỉ sau đó lệnh echo thực hiện một chuỗi ký tự trên đối số của mình: Phương thức __toString được gọi và trả về 20.

  4. 20 sẽ xuất.

9

Để trả lời bạn câu hỏi với một chút của mã.

$number = new Group(); 
echo gettype($number); 

$number = "20"; 
echo gettype($number); 

$number = 20; 
echo gettype($number); 

sẽ dẫn đến

object 
string 
integer 

Ba trường hợp:

  • Bạn không thể làm bất kỳ hoạt động số nguyên trên một đối tượng, đó là lý do tại sao mã của bạn không làm những gì bạn mong đợi. Phương pháp __toString sẽ được gọi là rất muộn, khi đầu ra acutal sẽ tính toán, sau khi bạn đã không thành công cố gắng thực hiện một phép toán với nó.
  • Bạn có thể để toán với chuỗi, vì PHP trong nội bộ chuyển đổi chúng trở lại con số
  • Rõ ràng bạn có thể làm toán với số nguyên

Bonus:

này sẽ làm việc:

$number = new Group(); 
echo 1 + "$number"; // 21 

Nó chuyển đổi đối tượng của bạn thành một chuỗi, có thể được chuyển đổi thành một số cho phép toán.

+0

Thêm một cách rõ ràng vào biểu thức biến thực sự mở ra cách thay đổi số tiền được thêm rất dễ dàng. Các hoạt động trước hoặc sau tăng nên tránh. Bạn sẽ không bao giờ thực sự biết điều gì sẽ xảy ra. [Douglas Crockford không thích chúng.] (Http://stackoverflow.com/questions/971312/why-avoid-increment-and-decrement-operators-in-javascript) - và trong PHP nó dễ dàng hơn để sử dụng phiên bản ngắn '$ i + = 1 ^' thay vì '$ i ++' - chỉ một ký tự nữa. Và cố gắng tăng thêm 2 ... :) – Sven

2

Tôi nghĩ rằng nó có thể là rõ ràng hơn với chỉ cần thay đổi tên của các biến như thế này:

class Group { 
    private $number = 20; 

    public function __toString() { 
     return "$this->number"; 
    } 
} 

$group = new Group(); 
echo $group;//print 20 as per your __toString function 

++ $group; 

Bây giờ có vẻ như rõ ràng: những gì là phải làm một '++' điều hành trên một đối tượng của nhóm loại ??

1

Tại sao bạn không chỉ:

class Group { 
    private $number = 0; 
    public function __construct($number = 0){ 
     $this->number = intval($number); 
    } 
    public function __toString() { 
     return number_format(++$this->number); // pre-increment 
    } 
} 
$g = new Group(); 
echo $g; // 1 
echo $g; // 2 

tôi sử dụng một cái gì đó như thế này để định dạng offsets trong bảng.

0

Đây là thực sự khả thi hơn bạn có thể nghĩ - chỉ cần làm nhiều hơn một chút loại đúc, như sau:

<?php 

class Group { 
private $number = 20; 

    public function __toString() { 
     return (string) $this->number; // replace "" w/string cast 
    } 
} 

$number = (int)(string) new Group(); 
echo $number, PHP_EOL; 
echo ++$number, PHP_EOL; 

Bạn không cần phải sử dụng chuỗi diễn viên của Tất nhiên trong phép thuật __toString() nhưng cá nhân tôi thích đọc mã theo cách đó hơn là nhìn thấy các dấu ngoặc kép - nhưng tôi nghĩ đó chỉ là một sở thích phong cách.

Truyền đối tượng mới tạo thành chuỗi làm cho phương thức __toString phép thuật tự động thực thi và trả về một chuỗi số khi được truyền tới int cho phép bạn hiển thị số, tăng số và hiển thị lại.

Ngẫu nhiên, khoảng cách giữa số ++ và $ là không sao; Tôi đóng nó lên b/c đó là những gì tôi đang sử dụng để trong các ngôn ngữ khác như C.

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