gọi một phương thức tĩnh bên trong một lớp?


166

Làm thế nào để tôi gọi một phương thức tĩnh từ một phương thức khác trong cùng một lớp?

$this->staticMethod();

hoặc là

$this::staticMethod();

13
Bạn có thể quan tâm đến điều này ( selfso với $this): stackoverflow.com/questions/151969/php-elf-vs-this
Felix Kling

Chỉ là một FYI, ví dụ đầu tiên của bạn là một biến đối tượng gọi một phương thức tĩnh là không thể bởi vì một phương thức tĩnh là một phần của lớp và không thể truy cập được thông qua một biến thể hiện.
joejoeson

bây giờ bạn có thể xóa $ this xin vui lòng nó không hoạt động nếu chỉ sử dụng các phương thức tĩnh và không có trường hợp nào tồn tại.
malhal

Câu trả lời:


321

...nhưng tại sao? $ this-> staticMethod () cũng hoạt động. Bạn có thể giải thích tại sao self :: staticMethod () đúng hơn (nếu có) không?
Ian Dunn

29
@Ian Dunn Đặt đơn giản, $thischỉ tồn tại nếu một đối tượng đã được khởi tạo và bạn chỉ có thể sử dụng $this->methodtừ bên trong một đối tượng hiện có. Nếu bạn không có đối tượng mà chỉ gọi một phương thức tĩnh và trong phương thức đó bạn muốn gọi một phương thức tĩnh khác trong cùng một lớp, bạn phải sử dụng self::. Vì vậy, để tránh các lỗi tiềm ẩn (và cảnh báo nghiêm ngặt), tốt hơn là sử dụng self.
jeroen

1
Cảm ơn! Trong laravel, tôi thấy rằng tôi đã vô tình gọi phương thức tĩnh qua bộ điều khiển mở rộng bằng cách sử dụng $this, nhưng vấn đề không xuất hiện cho đến khi mã được đẩy sang stage. không có lỗi trở lại, giá trị chỉ là 0. hãy cẩn thận với điều này, sử dụngself::
blamb

44

Giả sử đây là lớp học của bạn:

class Test
{
    private $baz = 1;

    public function foo() { ... }

    public function bar() 
    {
        printf("baz = %d\n", $this->baz);
    }

    public static function staticMethod() { echo "static method\n"; }
}

Từ bên trong foo()phương thức, chúng ta hãy xem xét các tùy chọn khác nhau:

$this->staticMethod();

Vì vậy, đó gọi staticMethod()là một phương thức ví dụ, phải không? Nó không. Điều này là do phương thức được khai báo là public statictrình thông dịch sẽ gọi nó là phương thức tĩnh, vì vậy nó sẽ hoạt động như mong đợi. Có thể lập luận rằng làm như vậy làm cho nó ít rõ ràng hơn từ mã mà một cuộc gọi phương thức tĩnh đang diễn ra.

$this::staticMethod();

Vì PHP 5.3 bạn có thể sử dụng $var::method()để có nghĩa <class-of-$var>::; Điều này khá thuận tiện, mặc dù trường hợp sử dụng ở trên vẫn còn khá độc đáo. Vì vậy, điều đó đưa chúng ta đến cách gọi phổ biến nhất của một phương thức tĩnh:

self::staticMethod();

Bây giờ, trước khi bạn bắt đầu nghĩ rằng ::các nhà điều hành cuộc gọi tĩnh, hãy để tôi cung cấp cho bạn một ví dụ khác:

self::bar();

Điều này sẽ in baz = 1, có nghĩa là $this->bar()self::bar()làm chính xác điều tương tự; đó ::chỉ là một toán tử phân giải phạm vi. Nó ở đó để thực hiện parent::, self::static::làm việc và cung cấp cho bạn quyền truy cập vào các biến tĩnh; làm thế nào một phương thức được gọi phụ thuộc vào chữ ký của nó và cách người gọi được gọi.

Để xem tất cả điều này trong thực tế, xem đầu ra 3v4l.org này .


self::bar()có vẻ sai lệch - bây giờ có bị phản đối không? (sử dụng self::để gọi một phương thức cá thể chứ không phải là một phương thức tĩnh).
ToolmakerSteve

@ToolmakerSteve theo cách bạn sẽ nói rằng nó sai lệch?
Ja͢ck

Nói một cách logic, không có selfkhi gọi một phương thức tĩnh. Theo định nghĩa: phương thức tĩnh có thể gọi được từ mọi nơi và không nhận được tham số "tự". Tuy nhiên, tôi thấy sự tiện lợi của phpcú pháp đó , để bạn không phải viết MyClassName::. Tôi đã quen với các ngôn ngữ gõ tĩnh, trong đó trình biên dịch phải được cung cấp tất cả các biến có sẵn trong phạm vi hiện tại, do đó (tương đương với) self::có thể được bỏ qua. Vì vậy, người ta chỉ nói self instanceMethod; không có lý do để nói self staticMethod.
ToolmakerSteve

15

Đây là một phản hồi rất muộn, nhưng thêm một số chi tiết về các câu trả lời trước đó

Khi gọi các phương thức tĩnh trong PHP từ một phương thức tĩnh khác trên cùng một lớp, điều quan trọng là phải phân biệt giữa selfvà tên lớp.

Lấy ví dụ mã này:

class static_test_class {
    public static function test() {
        echo "Original class\n";
    }

    public static function run($use_self) {
        if($use_self) {
            self::test();
        } else {
            $class = get_called_class();
            $class::test(); 
        }
    }
}

class extended_static_test_class extends static_test_class {
    public static function test() {
        echo "Extended class\n";
    }
}

extended_static_test_class::run(true);
extended_static_test_class::run(false);

Đầu ra của mã này là:

Lớp gốc

Lớp học mở rộng

Điều này là do selftham chiếu đến lớp mà mã nằm trong, chứ không phải là lớp mã mà nó được gọi từ đó.

Nếu bạn muốn sử dụng một phương thức được định nghĩa trên một lớp kế thừa lớp gốc, bạn cần sử dụng một cái gì đó như:

$class = get_called_class();
$class::function_name(); 

2
Tôi tìm thấy thông tin này. Một nit nhỏ, tôi sẽ không nói rằng các câu trả lời khác là "sai lệch". Chính xác hơn để nói rằng họ "không đầy đủ"; họ không giải quyết câu hỏi (không có nội dung self::) về trường hợp nào (hiếm) trong đó phương thức tĩnh A gọi phương thức tĩnh B khác và B đã bị ghi đè trong lớp con. IMHO, sẽ ít gây nhầm lẫn hơn khi hạn chế phương thức ghi đè lên phương thức "cá thể"; sử dụng khả năng đó một cách tiết kiệm ở cấp độ tĩnh. Nói cách khác, người đọc mã của bạn mong đợi phương thức ghi đè các phương thức cá thể (đó là bản chất của mã hóa OO), nhưng không phải là phương thức tĩnh.
ToolmakerSteve

1
Rất hữu ích và nó có ý nghĩa rằng một phần mở rộng của lớp không phải là lớp gốc. Do đó, lý do là selfsẽ không được sử dụng trong trường hợp đó. Bạn đã khai báo một lớp riêng như một phần mở rộng cho lớp đầu tiên. Sử dụng selftrong lớp mở rộng sẽ đề cập đến lớp mở rộng. Điều này không mâu thuẫn với các câu trả lời khác, nhưng nó chắc chắn giúp chứng minh phạm vi self.
iyrin

2

Trong phiên bản PHP sau này self::staticMethod();cũng sẽ không hoạt động. Nó sẽ ném lỗi tiêu chuẩn nghiêm ngặt.

Trong trường hợp này, chúng ta có thể tạo đối tượng cùng lớp và gọi theo đối tượng

đây là ví dụ

class Foo {

    public function fun1() {
        echo 'non-static';   
    }

    public static function fun2() {
        echo (new self)->fun1();
    }
}

Bạn có thể làm điều đó, mặc dù nếu fun1không sử dụng self, nó không hợp lý để biến nó thành một phương thức cá thể. Cách thích hợp để làm điều này trong php là khai báo public static function fun1, sau đó gọi bằng cách chỉ định lớp : Foo::fun1. Tôi chắc chắn đó là cách dự định để sửa lỗi tiêu chuẩn nghiêm ngặt đó.
ToolmakerSteve
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.