What does new self (); nghĩa là trong PHP?


110

Tôi chưa bao giờ thấy mã như thế này:

public static function getInstance()
{
    if ( ! isset(self::$_instance)) {
        self::$_instance = new self();
    }
    return self::$_instance;
}

Nó giống với new className() không?

BIÊN TẬP

Nếu lớp là lớp kế thừa, lớp đó trỏ tới?



@ stereofrog, bạn có nghĩa là mô hình singleton nên bị loại bỏ? Nhưng tất cả mọi thứ tồn tại đều có lý do, phải không?
user198729,

Ồ, tôi có xu hướng đồng ý với quan điểm này: singleton nên được thay thế bằng nhà máy
user198729

@stereofrog của Singleton là chất độc đối với thử nghiệm đơn vị, rất khó để thực hiện các thử nghiệm bất biến đối với một thứ thay đổi trạng thái từ lệnh gọi này sang lệnh gọi tiếp theo.
David

Thật không may, phương pháp này sẽ không mở rộng. Nó sẽ luôn cung cấp cho bạn một đối tượng mới từ lớp mà hàm này đã được định nghĩa.
Ares

Câu trả lời:


211

self trỏ đến lớp mà nó được viết.

Vì vậy, nếu phương thức getInstance của bạn nằm trong một tên lớp MyClass, thì dòng sau:

self::$_instance = new self();

Sẽ làm tương tự như:

self::$_instance = new MyClass();



Chỉnh sửa: một vài thông tin thêm, sau các ý kiến.

Nếu bạn có hai lớp mở rộng nhau, bạn có hai tình huống:

  • getInstance được định nghĩa trong lớp con
  • getInstance được định nghĩa trong lớp cha

Tình huống đầu tiên sẽ giống như thế này (Tôi đã xóa tất cả mã không cần thiết, ví dụ này - bạn sẽ phải thêm nó trở lại để có được hành vi singleton) *:

class MyParentClass {

}
class MyChildClass extends MyParentClass {
    public static function getInstance() {
        return new self();
    }
}

$a = MyChildClass::getInstance();
var_dump($a);

Tại đây, bạn sẽ nhận được:

object(MyChildClass)#1 (0) { } 

Mà có nghĩa selfMyChildClass- tức là lớp mà nó được viết.


Đối với tình huống thứ hai, mã sẽ như thế này:

class MyParentClass {
    public static function getInstance() {
        return new self();
    }
}
class MyChildClass extends MyParentClass {

}

$a = MyChildClass::getInstance();
var_dump($a);

Và bạn sẽ nhận được loại đầu ra này:

object(MyParentClass)#1 (0) { }

Có nghĩa selfMyParentClass- tức là ở đây, lớp mà nó được viết .




Với PHP <5.3, "lớp mà nó được viết" là quan trọng - và đôi khi có thể gây ra sự cố.

Đó là lý do tại sao PHP 5.3 giới thiệu một cách sử dụng mới cho statictừ khóa: bây giờ nó có thể được sử dụng chính xác nơi chúng ta đã sử dụng selftrong các ví dụ đó:

class MyParentClass {
    public static function getInstance() {
        return new static();
    }
}
class MyChildClass extends MyParentClass {

}

$a = MyChildClass::getInstance();
var_dump($a);

Nhưng, staticthay vì self, bây giờ bạn sẽ nhận được:

object(MyChildClass)#1 (0) { } 

Có nghĩa là staticloại đó trỏ đến lớp được sử dụng (chúng tôi đã sử dụng MyChildClass::getInstance()), chứ không phải lớp mà nó được viết.

Tất nhiên, hành vi của selfkhông được thay đổi, để không phá vỡ các ứng dụng hiện có - PHP 5.3 chỉ thêm một hành vi mới, tái chế statictừ khóa.


Và, nói về PHP 5.3, bạn có thể muốn xem trang Late Static Bindings của sổ tay PHP.


@Paul: heu ... có nghĩa là "tự đóng vai trò như một bí danh", hoặc "tự chỉ đến" - động từ "nhà thiết kế", trong tiếng Pháp, có thể được sử dụng cho điều đó - tôi cho rằng đó là một trong những tình huống trong đó sử dụng cùng một từ trong tiếng Anh không phải là một ý tưởng tốt ;-( tôi sẽ sửa câu trả lời của tôi để sửa lỗi này ;; nhờ :-)
Pascal MARTIN

Điều gì sẽ xảy ra nếu có baseclass, classcái nào nó trỏ đến?
user198729 Ngày

@ người dùng: Tôi đã chỉnh sửa câu trả lời của mình để cung cấp thêm một chút thông tin về selfvà kế thừa; và tôi cũng đã bao gồm một số thông tin về staticPHP 5.3 ;; hy vọng điều này sẽ giúp :-)
Pascal MARTIN

10

Đây dường như là một triển khai của mẫu Singleton . Hàm được gọi là static và kiểm tra xem lớp static có biến hay không$_instance .

Nếu không, nó sẽ khởi tạo một thể hiện của chính nó ( new self()) và lưu trữ trong$_instance .

Nếu bạn gọi, className::getInstance()bạn sẽ nhận được một và giống nhau cá thể lớp trong mỗi lần gọi, đó là điểm của mẫu singleton.

Tuy nhiên, tôi chưa bao giờ thấy nó được thực hiện theo cách này, và thành thật mà nói tôi không biết điều đó là có thể. Những gì được $_instancekhai báo như trong lớp?


1
$_instanceđược tuyên bố làpublic static $_instance;
Atif

7

Điều này rất có thể được sử dụng trong mẫu thiết kế singleton, trong đó hàm tạo được định nghĩa là private để tránh bị khởi tạo, (::)toán tử dấu hai chấm có thể truy cập các thành viên được khai báo tĩnh bên trong lớp, vì vậy nếu có các thành viên tĩnh, biến giả $ điều này không thể được sử dụng, do đó mã được sử dụng tự thay thế, Singletons là phương pháp lập trình tốt sẽ chỉ cho phép 1 phiên bản của một đối tượng như trình xử lý kết nối cơ sở dữ liệu. Từ mã máy khách, việc truy cập phiên bản đó sẽ được thực hiện bằng cách tạo một điểm truy cập duy nhất, trong trường hợp này anh ta đặt tên cho nó làgetInstance() , Bản thân getInstance là hàm tạo đối tượng về cơ bản bằng cách sử dụng từ khóa mới để tạo đối tượng nghĩa là phương thức khởi tạo là còn được gọi là.

dòng if(!isset(self::instance))kiểm tra xem một đối tượng đã được tạo hay chưa, bạn không thể hiểu được điều này vì mã chỉ là một đoạn, ở đâu đó trên cùng, nên có các thành viên tĩnh như có lẽ

private static $_instance = NULL; 

trong các lớp học bình thường, chúng tôi sẽ truy cập thành viên này bằng cách

$this->_instance = 'something';

nhưng nó được khai báo tĩnh và vì vậy chúng tôi không thể sử dụng $ this code mà chúng tôi sử dụng để thay thế

self::$_instance

bằng cách kiểm tra xem có một đối tượng được lưu trữ trên biến lớp tĩnh này hay không, lớp sau đó có thể quyết định tạo hay không tạo một cá thể duy nhất, vì vậy nếu nó không được đặt,! Isset, nghĩa là không có đối tượng nào tồn tại trên thành viên tĩnh $ _instance, thì nó tạo một đối tượng mới, được lưu trữ trong thành viên tĩnh $_instancebằng lệnh

self::$_instance = new self();

và trả về mã khách hàng. Sau đó, mã máy khách có thể vui vẻ sử dụng phiên bản duy nhất của đối tượng với các phương thức công khai của nó, nhưng trong mã máy khách, việc gọi điểm truy cập duy nhất, tức là, getInstance()phương thức cũng phức tạp, nó phải được gọi như thế này

$thisObject = className::getInstance();

lý do, hàm trong chính nó được khai báo tĩnh.


2

Có, nó giống như new className()(đề cập đến lớp chứa phương thức đó), có thể được sử dụng trong một mẫu Singleton trong đó hàm tạo là riêng tư.


Tại sao ai đó sẽ sử dụng mẫu Singleton trong PHP? Trừ khi được sử dụng trong một chương trình giống như daemon, singleton sẽ chỉ tồn tại trong khi tập lệnh chạy và sau đó biến mất cùng với chương trình.
ILikeTacos 16/10/13

4
để tránh irritatingly tuyên bố toàn cầu để truy cập vào một biến toàn cầu
Sam Adamsh

0

Nếu lớp được kế thừa thì việc gọi getInstance () từ con sẽ không cung cấp cho bạn một thể hiện của con. Nó sẽ chỉ trả về một thể hiện của cá thể mẹ. Điều này là do chúng ta gọi là new self ().

Nếu bạn muốn rằng lớp con sẽ trả về một thể hiện của lớp con thì hãy sử dụng new static () trong getInstance () và sau đó nó sẽ trả về thể hiện của lớp con. Đây được gọi là ràng buộc muộn !!

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.