[PHP] – Bài 7: Lập trình hướng đối tượng OOP trong PHP phần 2

0 8

Trong bài học này, chúng ta sẽ tiếp tục tìm hiểu một số vấn đề liên quan OOP như trait, phân biệt this, self, static, final.

Video Lập trình hướng đối tượng OOP trong PHP phần 2

Hướng dẫn chi tiết

Đa thừa kế với trait

PHP chỉ hỗ trợ class con kế thừa từ 1 lớp cha. Abstract class và Interface chỉ có tác dụng làm khuôn mẫu. Việc kế thừa từ Abstract class và Interface cần phải ghi đè lại các phương thức vì các phương thức chỉ mới được khai báo chứ chưa có code xử lý. Để giải quyết vấn đề này, PHP hỗ trợ trait. Tuy nhiên, trait chỉ hỗ trợ cho hàm (gọi là hàm vì trait không phải là class – khi nằm trong class hàm sẽ được gọi là phương thức).

trait Trait_1 {
    function say_hello(){
        echo 'Hello world';
    }
}
trait Trait_2 {
    function say_goodbye(){
        echo 'Good bye';
    }
}
class Trait_Example {
    use Trait_1;
    use Trait_2;
}

Xử lý xung đột khi trùng tên hàm. Dùng từ khóa insteadof để loại bỏ hàm bị trùng không dùng đến.

trait Trait_4 {
    function say_1(){
        echo 'Hi One';
    }
    function say_2(){
        echo 'Hi Two';
    }
}
trait Trait_5 {
    function say_protected(){
        echo 'Hi Protected';
    }
    function say_private(){
        echo 'Hi Private';
    }
}
class Trait_Example {
    use Trait_1;
    use Trait_2;
    use Trait_3, Trait_4 {
        Trait_3::say_1 insteadof Trait_4;
        Trait_4::say_2 insteadof Trait_3;
    }
}

Thay đổi quyền truy cập vào tên phương thức. Dùng từ khóa as để đặt lại tên và phân quyền truy cập.

trait Trait_5 {
    function say_protected(){
        echo 'Hi Protected';
    }
    function say_private(){
        echo 'Hi Private';
    }
}
class Trait_Example {
    use Trait_1;
    use Trait_2;
    use Trait_3, Trait_4 {
        Trait_3::say_1 insteadof Trait_4;
        Trait_4::say_2 insteadof Trait_3;
    }
    use Trait_5 {
        say_protected as protected ex_say_protected;
        say_private as private ex_say_private;
    }
}

Các bạn khởi tạo đối tượng và chạy thử nhé

Anonymous classes

Khi bạn chỉ cần đối tượng được sử dụng một lần, và không cần sử dụng lại thì PHP 7. cung cấp cho chúng ta một tính năng mới là đối tượng không định danh. Trong ví dụ bên dưới, hàm var_dump() chúng ta truyền vào một đối tượng làm đối số cho hàm.

var_dump(new class ('Đỏ',1){
    public $mau_sac;
    public $so_chan_ban;
    function __construct($mau_sac = null, $so_chan_ban = null){
        $this->mau_sac = $mau_sac;
        $this->so_chan_ban = $so_chan_ban;
    }
    function intro(){
       echo "Đây là bàn màu {$this->mau_sac} và có {$this->so_chan_ban} chân";
    }
});

self, parrent và $this

+ Cách dùng self: trỏ đến lớp hiện tại

+ Cách dùng parrent: trỏ đến class cha được kế thừa

+ Cách dùng $this: trỏ đến đối tượng hiện tại

Vài giây cho quảng cáo Hosting

Các bạn cần hosting PHP - WordPress nhanh, rẻ và dễ sử dụng có thể chọn Azdigi nhé.
Link đăng ký: https://my.azdigi.com/aff.php?aff=1612
Nếu các bạn đăng ký và sử dụng hosting, Góc Làm Web sẽ có một ít tiền để duy trì.

So sánh giữa self và $this

Sử dụng trong trường hợp kế thừa từ lớp cha

class Ban {
    public $mau_sac;
    public $so_chan;
    public function __construct($mau_sac = 'Trắng', $so_chan = 4){
        $this->mau_sac = $mau_sac;
        $this->so_chan = $so_chan;
    }
    public function intro(){
        echo "Đây là chiếc bàn màu {$this->mau_sac} và có {$this->so_chan} chân";
    }
    public function re_intro(){
        echo 'Hello';
        // self::intro();
        $this->intro();
    }
}
class Ban_2 extends Ban{
    public $chat_lieu;
    public function __construct($mau_sac = 'Trắng', $so_chan = 4,$chat_lieu = 'Gỗ'){
        $this->mau_sac = $mau_sac;
        $this->so_chan = $so_chan;
        $this->chat_lieu = $chat_lieu;
    }
    public function intro(){
        echo "Đây là chiếc bàn màu {$this->mau_sac} và có {$this->so_chan} chân, làm bằng {$this->chat_lieu}";
    }
}
$ban_2 = new Ban_2('Nâu',4,'Gỗ');
$ban_2->re_intro()

Các bạn chú ý đến hàm re_intro nhé.

Trong trường hợp dùng $this, hàm intro được gọi bên sẽ là hàm của lớp con Ban_2. Từ khóa $this sẽ gọi đến đối tượng hiện tại, được khởi tạo dựa trên lớp Ban_2. Do đó, hàm intro đã được ghi đè lại, thay đổi nội dung bên trong.

Trong trường hợp dùng self, hàm intro được gọi bên trong sẽ là hàm của lớp cha Ban. Từ khóa self sẽ gọi đến lớp cùng cấp với hàm re_intro. Lưu ý: chúng ta chưa ghi đè hàm re_intro nhé, chỉ kế thừa từ lớp cha. Do đó, lớp đang quản lý hàm re_intro là lớp Ban, không phải lớp Ban_2.

Nhắc lại, lớp (class) và đối tượng (object) là khái niệm khác nhau nhé. Các bạn có thể hiểu đơn giản là

+ Lớp (class) là bản vẽ, bản thiết kế, cấu trúc 1 một vật thể hay hành động nào đó.

+ Đối tượng (Object) là vật thể, hành động được khởi tạo, dựng nên từ bản vẽ (class).

Sử dụng trong trường hợp static

class Ban_3 {
    public static $mes = 'Đây là bàn';
    public static function mes(){
        // echo $this->mes;
        echo self::$mes;
    }
}
Ban_3::mes();

Chúng ta có 1 thuộc tính tĩnh là $mes. Khi truy xuất đến thuộc tính tĩnh, chúng ta không thể dùng $this$this trỏ đến đối tượng hiện tại, nhưng thuộc tính tĩnh không cần khởi tạo đối tượng vẫn có thể sử dụng được. Do đó, chúng ta phải dùng self, trỏ đến lớp hiện tại.

So sánh giữa static và final

class Ban_4 {
    // public final $mes = 1;
    public final function mes(){
        echo 'Đây là tin nhắn final';
    }
    public static function mes_2(){
        echo 'Đây là tin nhắn static';
    }
}
class Ban_5 extends Ban_4{   
    // public final function mes(){
    //     echo 'Đây là tin nhắn final kế thừa';
    // }
    public static function mes_2(){
        echo 'Đây là tin nhắn static kế thừa';
    }
}
Ban_5::mes();
Ban_5::mes_2();

static (dùng cho thuộc tính và phương thức) và final (chỉ dùng cho phương thức) đều được dùng để khai báo tĩnh. Khác biệt ở chỗ final không thể kế thừa và ghi đè lại.

So sánh giữa self và static

Sử dụng cho lớp hiện tại

class Ban_6 {
    public static $mes = 'Lời nhắn';
    public function mes(){
        echo self::$mes;
        // echo static::$mes;
    }
}
$b6 = new Ban_6();
$b6->mes();

Lưu ý: thuộc tính $mes là thuộc tính tĩnh.

Trong trường hợp dùng cho nội bộ class thì kết quả giống nhau. Cả self và static đều sử dụng được cho thuộc tính tĩnh. Các bạn chạy thử 2 trường hợp để xem kết quả nhé.

Sử dụng trong trường hợp kế thừa từ lớp cha

class Ban_7 extends Ban_6 {
    public static $mes = 'Tin nhắn';
}
$b7  = new Ban_7();
$b7->mes();

Trong trường hợp kế thừa lớp, kết quả sẽ khác nhé. Lúc này, static sẽ cho ra kết quả tương tự như $this trong phần So sánh self và $this.

Code mẫu: Download

Nếu có thắc mắc, hãy đặt câu hỏi bằng cách comment bên dưới, qua email, hoặc nhắn tin qua Fanpage Góc làm web.

Liên hệ

Để lại một trả lời

Địa chỉ email của bạn sẽ không được công bố.