PHP Traits là gì ? Dùng thử PHP Traits

Bài viết đã được chuyển sang blog của Haposoft. Để xem nội dung được cập nhật mới nhất, mời bạn xem tại link: https://blog.haposoft.com/php-traits-la-gi-dung-thu-php-traits/

PHP Traits là gì ?

PHP, Java hay Ruby đều là những ngôn ngữ hướng đối tượng chỉ hỗ trợ single inheritance(đơn kế thừa). Để khắc phục những giới hạn của đơn kế thừa trong việc sử dụng lại source code, từ PHP 5.4 trở đi PHP hỗ trợ Traits là cơ chế giúp cho lập trình viên có thể sử dụng lại các phương thức từ các class khác nhau một cách dễ dàng hơn.

Traits cũng tương tự như class, nhưng chỉ được dùng với mục đích nhóm lại một số chức năng một cách đồng nhất. Để đơn giản, hãy dùng thử Traits qua ví dụ.

Ví dụ về Traits

Chúng ta sẽ thử một ví dụ về việc kế thừa. Ta sẽ thử với 3 lớp:

  • Human: có thể talk
  • Developer: ngoài talk, anh ấy còn code
  • Tester: tester chỉ cần biết test mà không cần code.

Thông thường chúng ta sẽ định nghĩa như sau:
(trong ví dụ này mình lưu vào file có tên là traits_test.php)

class Human  
{
    public function talk()
    {
        echo "I can talk";
    }
}

class Developer extends Human  
{
    public function code()
    {
        echo "I can code";
    }
}

class Tester extends Human  
{
    public function test()
    {
        echo "I can test";
    }
}

Để dễ dàng trực quan, ta sẽ thêm 1 static method có tên là canDo vào class Human để có thể dễ dàng kiểm tra xem ai có thể làm gì nhé :D .

class Human  
{
.....
    public static function canDo()
    {
        $message = '';

        $methods = get_class_methods(static::class);
        foreach ($methods as $method) {
            if ($method == __FUNCTION__) continue;
            $message .= " `$method`";
        }

        echo static::class . ' can do:' . $message . PHP_EOL;
    }
}

method canDo() sẽ làm nhiệm vụ liệt kê tất cả các method có trong class hiện tại ngoại trừ nó, qua đó ta có thể biết được ai làm được những gì bằng việc gọi method này.

<?php

class Human  
{
    public function talk()
    {
        echo "I can talk";
    }

    public static function canDo()
    {
        $message = '';

        $methods = get_class_methods(static::class);
        foreach ($methods as $method) {
            if ($method == __FUNCTION__) continue;
            $message .= " `$method`";
        }

        echo static::class . ' can do:' . $message . PHP_EOL;
    }
}

class Developer extends Human  
{
    public function code()
    {
        echo "I can code";
    }
}

class Tester extends Human  
{
    public function test()
    {
        echo "I can test";
    }
}

//Check 
Human::canDo();  
Developer::canDo();  
Tester::canDo();  

Trên console bạn test thử file php này sẽ cho kết quả tương tự như bên dưới:

$ php traits_test.php 
Human can do: `talk`  
Developer can do: `code` `talk`  
Tester can do: `test` `talk`  

Bạn có thể thấy là Developer và Tester đều được kế thừa từ lớp Human nên cả 2 class đều có thể sử dụng method Talk.

Vấn đề là trong team của mình lại có những người được gọi là SuperMan, họ có thể vừa làm tốt cả 2 việc codetest, và tất nhiên khi kể về các SuperMan này, mình sẽ phải nói rằng

SuperMan can do: test code talk

Để sử dụng lại được method talk() từ class Developertest từ class Tester, trong PHP chúng ta sẽ làm như thế nào?

Hãy thử dùng Traits.

Mình sẽ định nghĩa 2 traits mới có tên là CodableTestablevới cú pháp như sau:

trait Codable  
{
    public function code()
    {
        echo 'I can code';
    }
}
trait Testable  
{
    public function test()
    {
        echo 'I can test';
    }
}

Để sử dụng các method này trong các class Developer, Tester, SuperMan bạn chỉ cần sử dụng traits trong các class đó như phía dưới:

trait Codable  
{
    public function code()
    {
        echo 'I can code';
    }
}

trait Testable  
{
    public function test()
    {
        echo 'I can test';
    }
}

//class Human không thay đổi
class Human{...}

class Developer extends Human  
{
    use Codable;
}

class Tester extends Human  
{
    use Testable;
}

class SuperMan extends Human  
{
    use Codable, Testable;
}

Human::canDo();  
Developer::canDo();  
Tester::canDo();  
SuperMan::canDo();

Kết quả:

$ php traits_test.php 
Human can do: `talk`  
Developer can do: `talk` `code`  
Tester can do: `talk` `test`  
SuperMan can do: `talk` `code` `test`

Khá đơn giản có phải không?
Thay vì kế thừa từ nhiều class khác nhau, trong PHP bạn có thể dùng traits để có thể sử dụng lại các method một cách hợp lý.

Source code của ví dụ trên có thể download tại Github Repo