2011-07-06 31 views
13

Cho đến ngày hôm nay, tôi nghĩ rằng tôi đã nắm bắt khá tốt cách thức công cụ sửa đổi tĩnh hoạt động. Tôi biết rằng (trong thuật ngữ laymans) một biến tĩnh trong một hàm không 'đặt lại' qua các cuộc gọi đến hàm đó, và tôi biết rằng các biến tĩnh và các hàm trên một lớp có thể truy cập được bằng cách gọi chúng thông qua chính lớp đó của lớp).Biến PHP và tĩnh trong các hàm thành viên đối tượng

Vấn đề của tôi là thế này: hôm nay tôi phát hiện ra rằng nếu tôi khai báo một biến tĩnh bên của một tổ chức phi tĩnh chức năng vào một lớp học, tất cả sự khởi tạo của lớp chia sẻ mà biến tĩnh trong các cuộc gọi riêng biệt với chức năng thành viên .

Ví dụ:

class A { 
    public function GetValue() { 
     static $value = 0; 
     $value++; 
     return $value; 
    } 
} 

$instance_1 = new A(); 
$instance_2 = new A(); 
echo $instance_1->GetValue(); 
echo $instance_1->GetValue(); 

echo $instance_2->GetValue(); 
echo $instance_2->GetValue(); 

echo $instance_1->GetValue(); 
echo $instance_1->GetValue(); 

Chú ý rằng chức năng GetValue không phải là dự khai báo là tĩnh hoặc sử dụng một cách tĩnh (như trong, kêu gọi các tầng lớp chính nó).

Bây giờ, tôi luôn luôn giả định rằng điều này sẽ ra: 121234

Thay vào đó, tôi thấy rằng nó sẽ ra: 123456

Giống như tôi đã nói, tôi sẽ hiểu được điều này nếu $ giá trị biến tĩnh là bên trong một hàm tĩnh. Tuy nhiên, với nó nằm bên trong một hàm không tĩnh, tôi chỉ giả định rằng nó sẽ chỉ được 'gắn' với hàm 'bên trong' mỗi sự khởi tạo riêng lẻ.

Tôi đoán câu hỏi của tôi là gấp đôi, sau đó ... 1) đây có phải là lỗi hoặc hành vi dự kiến ​​không? 2) làm các ngôn ngữ khác đối xử với các biến 'tĩnh bên trong không tĩnh' theo cùng một cách, hoặc là duy nhất này cho PHP?

+0

Tôi đã xem một số câu hỏi về SO về hành vi của 'tĩnh' trong PHP. Có vẻ như đây là một khu vực thiếu tài liệu - dù về số lượng hay chất lượng. –

+0

* (tham chiếu) * [biến tĩnh] (http://php.net/manual/en/language.variables.scope.php#language.variables.scope.static) – Gordon

+0

đó là hút. Tôi nghĩ "tĩnh" trong trường hợp này có nghĩa là biến sẽ không được đặt lại cho 'đối tượng' này, nhưng không phải cho 'lớp'. Một lần nữa hành vi chống trực quan. Và nếu trong các hành vi ngôn ngữ khác là như nhau - tất cả chúng chỉ là những kẻ ngu ngốc ngu ngốc. Phương thức này không tĩnh, vì vậy phương thức thuộc về cá thể đối tượng. Biến thuộc về phương thức, do đó biến sẽ chỉ thuộc về đối tượng, không phải lớp. Ahh ... –

Trả lời

5
  1. Điều này được mong đợi.
  2. Đây cũng là trường hợp trong C++ (và có thể là những trường hợp khác).

Bạn nên nghĩ về các chức năng thành viên của lớp không tĩnh như thể chúng giống như các hàm bình thường, nhưng với đối số ngụ ý $this được trình thông dịch tự động cung cấp. (Đó chính xác là cách chúng được triển khai bằng hầu hết các ngôn ngữ.)

1

Theo như tôi biết, tất cả các ngôn ngữ có biến tĩnh xử lý chúng theo cách này. Hãy suy nghĩ về các biến tĩnh dưới dạng các biến toàn cầu mà chỉ có thể được truy cập từ một phạm vi nhất định.

+0

Trong khi tôi thích cách nhìn này, tôi nghĩ rằng tôi vẫn còn lúng túng, đủ để nói rằng tôi không nghĩ rằng nó nên được thực hiện theo cách này ở nơi đầu tiên: s – Narcissus

+0

Nếu bạn muốn một biến giữ giá trị của nó trên lớp phương thức invocations, @Narcissus, chỉ cần sử dụng một biến thành viên chuẩn. –

+0

hầu hết thời gian tôi làm điều này, nhưng tôi thích ý tưởng về một chức năng có thể lưu vào bộ nhớ cache kết quả của chính nó để trở về sau, mà không có bộ nhớ cache gây ô nhiễm cho chính lớp đó. – Narcissus

4

tôi đã sao chép các thông tin sau từ bài viết này bởi Josh Duck: http://joshduck.com/blog/2010/03/19/exploring-phps-static-scoping/

biến tĩnh đã có từ PHP 4 và cho phép bạn xác định một biến dai dẳng mà chỉ truy cập từ các chức năng hiện hành. Điều này cho phép bạn đóng gói trạng thái vào một hàm hoặc phương thức và có thể loại bỏ sự cần thiết cho các lớp mà ở đó một hàm duy nhất sẽ đủ.

Khi biến tĩnh được xác định bên trong một phương thức lớp, chúng sẽ luôn tham chiếu đến lớp mà phương thức được gọi. Khi làm điều này, chúng hoạt động giống như các thuộc tính được tham chiếu thông qua tĩnh, mặc dù có những khác biệt nhỏ.

Biến tĩnh không thể duy trì phạm vi lớp gọi. Điều này có thể có khả năng có vấn đề nếu bạn có một phương thức kế thừa có chứa một biến tĩnh được gọi từ cả bên trong lẫn bên ngoài lớp của nó.

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