Khoa học công nghệ

Cách sử dụng thuộc tính Readonly trong PHP 8.1

Logo PHP

PHP 8.1 bổ sung hỗ trợ cho một readonly sửa đổi trên các thuộc tính của lớp. Thuộc tính được gắn thẻ theo cách này chỉ có thể được đặt một lần. Cố gắng thay đổi giá trị của thuộc tính chỉ đọc sau khi khởi tạo sẽ gây ra lỗi.

“Readonly” là một thuật ngữ khá mơ hồ, với các hàm ý khác nhau trong các ngôn ngữ lập trình riêng lẻ. Trong ngữ cảnh này, “readonly” thực sự có nghĩa là “bất biến” —bạn có thể đặt giá trị của một thuộc tính, nhưng không thể thay đổi nó sau đó.

Viết thuộc tính chỉ đọc

Thêm readonly sửa đổi để làm cho một thuộc tính chỉ đọc. Nó phải được đặt giữa công cụ sửa đổi quyền truy cập của thuộc tính và kiểu chữ của nó.

class Demo {
 
    public string $Mutable;
 
    public readonly string $Immutable;
 
    public function __construct(
        string $Mutable,
        string $Immutable) {
 
        $this -> Mutable = $Mutable;
        $this -> Immutable = $Immutable;
    }
 
}

$Mutable là tài sản công thường xuyên. Bạn có thể thay đổi giá trị của nó bất kỳ lúc nào, trong các phương thức lớp hoặc từ bên ngoài:

$demo = new Demo("A", "X");
$demo -> Mutable = "B";

$Immutable là một chút khác nhau. Bạn vẫn có thể đọc giá trị của nó bất cứ khi nào bạn muốn, nhưng bất kỳ sửa đổi nào sẽ không thành công với Error:

// Throws an Error
$demo -> Immutable = "Y";

Các readonly modifier cũng được hỗ trợ trong các thuộc tính hàm tạo được quảng bá:

class Demo {
    public function __construct(
        public readonly string $Immutable="foobar"
    ) {}
}

Bạn vẫn có thể đặt thuộc tính theo cách thủ công trong hàm tạo của mình khi bạn đang sử dụng quảng cáo có giá trị mặc định. Đó là tham số chức năng nhận giá trị mặc định, không phải phiên bản thuộc tính. Chương trình khuyến mại giải mã về cùng một mã được hiển thị trong ví dụ trước đó.

Cảnh báo

Thuộc tính chỉ đọc là một cải tiến cú pháp đơn giản mà bạn có thể áp dụng khi rảnh rỗi. Không có tác động tương thích ngược và việc sử dụng chúng là hoàn toàn tùy chọn. Nếu bạn bắt đầu thêm chúng, có một số lưu ý và hạn chế cần lưu ý.

Không giống như các thuộc tính thông thường, các thuộc tính chỉ đọc không được phép có giá trị mặc định trong định nghĩa của chúng:

class Demo {
    protected readonly string $foo = "bar";
}

Câu lệnh này định nghĩa và khởi tạo $foo. Bạn không thể thay đổi giá trị của nó sau khi khởi tạo, vì vậy thuộc tính thực sự là một hằng số. Do đó, các giá trị mặc định bị cấm và thay vào đó bạn nên sử dụng một hằng số thực:

class Demo {
    const foo = "bar";
}

Tiếp theo từ hạn chế này, readonlychỉ một được hỗ trợ trên các thuộc tính đã nhập. Thuộc tính sau có định nghĩa bất hợp pháp:

class Demo {
    protected readonly $foo;
}

Thuộc tính không định dạng, như $foo ở trên, có giá trị mặc định tiềm ẩn là null. Nếu như readonly được cho phép, quy tắc “không có hằng số ngầm định” sẽ hoạt động trở lại. Thuộc tính đã nhập phân biệt giữa trạng thái “chưa được khởi tạo” và “null”, vì vậy chúng tồn tại mà không có bất kỳ giá trị nào cho đến khi bạn đặt một cách rõ ràng.

Công cụ sửa đổi chỉ đọc có các quy tắc đặc biệt khi được sử dụng như một phần của kế thừa lớp. Các lớp con không thể thêm hoặc bớt readonly trên các tài sản được xác định bởi cha mẹ của họ.

Tạo thuộc tính có thể ghi readonly sẽ phá vỡ lớp cha nếu các phương thức của nó thay đổi giá trị. Mặc dù việc loại bỏ ràng buộc dường như vô hại, nhưng quan điểm của RFC readonly như một “hạn chế có chủ ý” các khả năng sẽ bị mất nếu cho phép ghi đè kế thừa. Nó bị cấm để các lớp cha mẹ có thể khẳng định rằng trẻ em không thể gây ra tác dụng phụ bằng cách sửa đổi các thuộc tính có nghĩa là chỉ đọc.

Thuộc tính chỉ đọc chỉ có thể được đặt trong phạm vi mà chúng được xác định. Điều này có nghĩa rằng public Không thể đặt thuộc tính từ bên ngoài một lớp, ngay cả khi chúng chưa được khởi tạo trước đó:

class Demo {
    public readonly string $foo;
}
 
$d = new Demo();
$d -> foo = "bar";  // illegal

Khởi tạo phải xảy ra trong lớp xác định thuộc tính. Do đó, các thuộc tính chỉ đọc gần giống với các trường bất biến của các ngôn ngữ lập trình khác, trái ngược với các thuộc tính PHP đã có từ trước.

Các readonly sửa đổi áp dụng như nhau cho tất cả các lần viết. Nó không phân biệt giữa truy cập nội bộ và bên ngoài. Bạn không thể có một thuộc tính chỉ đọc công khai nhưng có thể ghi trong lớp, mặc dù phần mở rộng thông số kỹ thuật trong tương lai có thể cho phép nó.

Một gotcha cuối cùng liên quan đến clone từ khóa. Mã này sẽ không hoạt động:

class Demo {
    public function __construct(
        public string $foo
    ) {}
}
 
$d = new Demo("bar");
$d2 = clone $d;
$d2 -> foo = "foobar";

Nhân bản tuân theo các quy tắc tương tự như truy cập tài sản thông thường. Mặc dù sự thay đổi thành foobar là lần đầu tiên foo được truy cập vào $d2, thuộc tính đã được khởi tạo bằng quá trình nhân bản. Có một khởi tạo ngầm trong quá trình sao chép.

Khi nào sử dụng thuộc tính Readonly?

Thuộc tính chỉ đọc sẽ đẩy nhanh đáng kể việc tạo các lớp đơn giản, đại diện cho cấu trúc dữ liệu. Thông thường người ta thường viết các lớp bỏ đi để chứa các tham số yêu cầu HTTP, đối tượng truyền dữ liệu và dữ liệu phản hồi. Chúng thường là bất biến, nơi các thuộc tính không được mong đợi thay đổi sau khi lớp được xây dựng.

Trước đây, bạn có hai lựa chọn không hấp dẫn khi viết các lớp dạng cấu trúc: sử dụng thuộc tính công khai, tăng tốc độ phát triển nhưng cho phép sửa đổi hoặc dành thời gian thêm các phương thức getter theo cách thủ công để hiển thị các thuộc tính được bảo vệ.

// Not ideal - Properties could be modified externally
class UserCreationRequest {
    public function __construct(
        public string $Username,
        public string $Password
    ) {}
}
 
// Not ideal either - Lots of boilerplate code
class UserCreationRequest {
    public function __construct(
        protected string $Username,
        protected string $Password
    ) {}
 
    public function getUsername() : string {
        return $this -> Username;
    }
 
    public function getPassword() : string {
        return $this -> Password;
    }
}

Các thuộc tính chỉ đọc cuối cùng cũng làm cho phương pháp tiếp cận lý tưởng trở nên khả thi:

class UserCreationRequest {
    public function __construct(
        public readonly string $Username,
        public readonly string $Password
    ) {}
}

Các thuộc tính có thể truy cập công khai nhưng không thể thay đổi. Kết hợp với việc thúc đẩy thuộc tính phương thức khởi tạo, các thuộc tính chỉ đọc hứa hẹn sẽ giảm đáng kể mã soạn sẵn, cho phép bạn viết các lớp hữu ích nhanh hơn.

readonly cũng hỗ trợ khả năng đọc mã và chỉ ra ý định của bạn tốt hơn. Bất kỳ ai đọc hoặc chỉnh sửa UserCreationRequest lớp biết rằng các thuộc tính của nó không có nghĩa là thay đổi. Trong ví dụ đầu tiên, không biết liệu mã khác trong dự án có sửa đổi trực tiếp các thuộc tính của lớp hay không. Ví dụ thứ hai rõ ràng hơn một chút, nhưng vẫn có thể khiến nhà phát triển triển khai thừa setUsername()setPassword() các phương pháp.

Sự kết luận

Các readonly modifier mang đến hỗ trợ bất biến được tích hợp sẵn cho các thuộc tính của lớp PHP. Nó làm cho mã của bạn rõ ràng hơn và ngăn chặn các thay đổi giá trị không chủ ý bằng cách thực thi tính bất biến trong thời gian chạy.

Nhìn lại loạt bài phát hành PHP 7, việc tạo một lớp giống cấu trúc cơ bản được sử dụng để xác định các thuộc tính đã định kiểu, viết một hàm tạo đặt các thuộc tính đó và sau đó thêm các phương thức getter để hiển thị các giá trị của chúng. Với PHP 8.1, bạn có thể cô đọng tất cả những thứ đó thành một chữ ký phương thức khởi tạo duy nhất bằng cách kết hợp public readonly và khuyến mãi tài sản.

Thuộc tính chỉ đọc được triển khai trong các bản dựng phát triển PHP 8.1 mới nhất. Bản phát hành sẵn sàng sản xuất sẽ đến vào tháng 11 năm 2021.

Leave a Comment

Stt buồn về cuộc sống mới nhất 2021