Sử dụng từ khóa static (ok)
https://freetuts.net/thuoc-tinh-va-phuong-thuc-tinh-trong-lap-trinh-huong-doi-tuong-php-170.html
Last updated
https://freetuts.net/thuoc-tinh-va-phuong-thuc-tinh-trong-lap-trinh-huong-doi-tuong-php-170.html
Last updated
Đăng bởi: TheHalfHeart- Vào ngày: 05-10-2014- View: 29559
Như ta biết mỗi đối tượng luôn có các thuộc tính, phương thức và muốn sử dụng được nó ta phải khởi tạo đối tượng đó gán vào một biến sau đó gọi đến. Nhưng giả sử chúng ta tạo hai hai biến cùng một đối tượng đó thì các thao tác xử lý trên hai biến đó (thực chất là 2 object) không ảnh hưởng lẫn nhau. Và nếu bạn đã đọc qua bài hàm và khai báo hàm trong php thì sẽ có khái niệm biến cục bộ và biến toàn cục, với ví dụ trên thì ta có thể hiểu mỗi thao tác chỉ ảnh hưởng trên chính biến đó chứ không ảnh hưởng qua các biến khác nên có thể gọi là cục bộ. Nhưng trong thực tế đôi lúc ta muốn bất kỳ thao tác nào đều được lưu lại trên đối tượng đó (dạng toàn cục) thì kiểu dữ liệu tĩnh chính là mấu chốt của vấn đề này.
Nội dung chính
Trong lập trình hướng đối tượng ta có thể hiểu dữ liệu tĩnh là loại dữ liệu được sử dụng ở dạng toàn cục, dù nó được xử lý ở bất kỳ file nào trong cùng một chương trình đều được lưu lại trong lớp, ta có thể gọi chúng là thành viên tĩnh. Mỗi thành viên đều có các mức truy cập private, public và protected bình thường.
Ví dụ 1: chương trình ở phần mở đầu.
123456789101112131415161718192021222324
// Lớp động vậtclass
Animal{ protected
$_name
=
'Chưa có tên';
function
setName($name){ $this->_name =
$name; }
function
getName(){ return
$this->_name; }}
// Phần 1: Con Vịt$con_vit
=
new
Animal();$con_vit->setName('Con Vịt');echo
$con_vit->getName();// Kết quả: Con Vịt
// Phần 2: Con Heo$con_heo
=
new
Animal();echo
$con_heo->getName();// Kết quả: Chưa có tên
Ta thấy ở Phần 1 tôi đã tạo object $con_vit
và thiết lập tên cho nó là 'Con Vịt'. Tiếp theo tôi tạo một object $con_heo
và tôi không có thiết lập tên cho nó, khi xuất tên ra màn hình thì Phần 1 xuất hiện chữ 'Con Vịt' còn Phần 2 thì xuất hiện chữ 'Chưa có tên'. Như vậy rõ ràng các thao tác trên biến $con_vit
không ảnh hưởng qua biến $con_heo
.
Ví dụ 2: chương trình dùng dạng thành viên tĩnh
123456789101112131415161718192021222324
// Lớp động vậtclass
Animal{ protected
static
$_name
=
'Chưa có tên';
public
static
function
setName($name){ Animal::$_name
=
$name; }
public
static
function
getName(){ return
Animal::$_name; }}
// Phần 1: Con Vịt$con_vit
=
new
Animal();$con_vit->setName('Con Vịt');echo
$con_vit->getName();// Kết quả: Con Vịt
// Phần 2: Con Heo$con_heo
=
new
Animal();echo
$con_heo->getName();// Kết quả: Con Vịt
Trong ví dụ này khác ở ví dụ 1 là các phương thức và thuộc tính tôi khai báo dạng tĩnh (có từ khóa static) và kết quả hoàn toàn khác với ví dụ 1. Ở cả Phần 1 và Phần 2 đều xuất ra màn hình là 'Con Vịt', lý do là tôi sử dụng dạng tĩnh và khi có thao tác thay đổi dữ liệu thì nó đều lưu vào trong class Animal nên khi khởi tạo thêm biến nó đều bị ảnh hưởng theo.
Qua hai ví dụ này có lẽ các bạn cũng đã hình dung được phần nào rồi, ta sẽ tiếp tục tìm hiểu sâu hơn nữa nhé.
Như đã trình bày ở trên các thành viên tĩnh đều có các mực truy cập bình thường. Và để khai báo các mức truy cập thì ta sử dụng cú pháp sau:
Cú pháp:
Thuộc tính: [private|public|protected] static $name
, ví dụ public static $name
Phương thức: [private|public|protected] static function functionname(){}
, ví dụ public static function setName()
Bây giờ ta sẽ thảo luận đến một số vấn đề khi sử dụng thành viên tĩnh.
1234567891011121314151617
// Lớp động vậtclass
Animal{ protected
static
$_name
=
'Chưa có tên';
public
static
function
setName($name){ Animal::$_name
=
$name; }
public
static
function
getName(){ return
Animal::$_name; }}
Animal::setName('Con Vịt');echo
Animal::getName();// Kết quả: Con Vịt
123456789101112131415161718192021
// Lớp động vậtclass
Animal{ protected
static
$_name
=
'Chưa có tên';
public
static
function
setName($name){ Animal::$_name
=
$name; }
public
static
function
getName(){ return
Animal::$_name; }
public
static
function
all($name){ Animal::setName($name); echo
Animal::getName(); }}
Animal::all('Con Vịt');// Kết quả: Con Vịt
Các bạn để ý trong ví dụ này tôi đã gọi các thành viên tĩnh nội bộ lẫn nhau trong chính đối tượng đó thông qua cú pháp hai dấu chấm (::). Tương tự khi sử dụng ở ngoài lớp ta vẫn dùng hai dấu chấm thay vì dấu mũi tên. Có một lưu ý rằng khi gọi đến thuộc tính tĩnh thì thông thường ta dùng $this->name
, nhưng trong thành viên tĩnh thì khác ta dùng thêm dấu $ nữa, ví dụ Anmal::
$
name
$this
Vì các thuộc tính và phương thức tĩnh ở dạng toàn cục, được gọi mà không cần khởi tạo nên nếu bạn dùng từ khóa $this
để gọi đến một hàm nào đó trong chính lớp đó thì sẽ bị báo sai. Từ đây ta rút ra kết luận trong phương thức tĩnh chỉ gọi được những thuộc tính và phương thức cùng class ở dạng tĩnh. Ngoài cách gọi trực tiếp tên class ta có thể dùng từ khóa self để thay thế, ví dụ self::$_name
12345678910111213141516171819202122
// Lớp động vậtclass
Animal{ protected
$_age
=
'';
protected
static
$_name
=
'Chưa có tên';
public
static
function
setInfo($name,
$age) { // Đúng Animal::$_name
=
$name;
// Sai vì $this không tồn tại $this->_name =
$name;
// Sai vì $this không tồn tại $this->_age =
$age;
// Sai vì thuộc tính $_age không phải là tĩnh Animal::$_age
=
$age; }}
Về tính kế thừa thì nó hoàn toàn bình thường không có gì đặc biệt, chỉ khác một điều là dùng hai dấu chấm (::) để truy xuất đến hàm tĩnh của lớp cha.
123456789101112131415161718192021222324252627
// Lớp động vậtclass
Animal{ protected
static
$_name
=
'';
public
static
function
setName($name) { Animal::$_name
=
$name; }
public
static
function
getName(){ return
Animal::$_name; }}
class
ConHeo
extends
Animal{
public
static
function
setName($name) { parent::setName($name); }
}
ConHeo::setName('Con Heo');echo
ConHeo::getName();// Kết quả: COn Heo
Việc sử dụng các hàm và thuộc tính ở dạng tĩnh có ưu điểm là ta có thể thay đổi dữ liệu toàn cục cho đối tượng đó, không cần khởi tạo đối tượng mới vẫn sử dụng được. Tuy nhiên nó có khuyết điểm là nếu ta khai báo tĩnh thì chương trình sẽ xử lý lưu trữ toàn cục nên sẽ tốn bộ nhớ hơn.
Trong thực tế các thuộc tính phương thức tĩnh được sử dụng rất nhiều trong lập trình hướng đối tượng, nó là một phần không thể thiếu trong OOP nên chắc chắn ban phải nắm vững rồi :D