Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> PHP

Traits trong PHP

Giới thiệu

PHP không hỗ trợ multiple inheritance (kế thừa đa kế). Hạn chế này được khắc phục một phần bằng tính năng traits. Đây là cơ chế tái sử dụng code (code reuse). Định nghĩa trait tương tự class. Tuy nhiên, nó không thể instantiate trực tiếp. Thay vào đó, chức năng của trait được cung cấp cho class bằng từ khóa use. Do đó, một class có thể dùng method định nghĩa trong trait hoặc thậm chí override chúng. Điều này bổ sung cho bất kỳ parent class nào mà nó đang kế thừa.

Trait cũng tương tự interface. Khác biệt: interface không cung cấp định nghĩa method bên trong, phải do implementing class làm. Trait method cung cấp định nghĩa, có thể hoặc không bị override bởi class dùng trait.

Cú pháp

<?php
trait TestTrait {
    public function test1() {
        // body của method
    }
}

// Sử dụng trait
class TestClass {
    use TestTrait;
    // các member khác của class
}
?>

Ví dụ

Trait cơ bản và override method

<?php
// Định nghĩa trait
trait TestTrait {
    public function test1() {
        echo "test1 method in trait\n";
    }
    public function test2() {
        echo "test2 method in trait\n";
    }
}

// Sử dụng trait
class TestClass {
    use TestTrait;
    public function test1() {
        echo "test1 method overridden\n";
    }
}
$obj = new TestClass();
$obj->test1();
$obj->test2();
?>

Kết quả

test1 method overridden
test2 method in trait

Trait trong child class (Kế thừa + Trait)

Đây là ưu điểm chính của trait. Class có parent cũng có thể dùng trait và chọn override method. Hiệu quả đạt được multiple inheritance.

<?php
// Trait
trait TestTrait {
    public function test1() {
        echo "test1 method in trait\n";
    }
}

// Parent class
class ParentClass {
    public function test2() {
        echo "test2 method in parent\n";
    }
}

// Child class dùng trait và extends parent
class ChildClass extends ParentClass {
    use TestTrait;
    public function test1() {
        echo "parent method overridden\n";
    }
    public function test2() {
        echo "trait method overridden\n";
    }
}
$obj = new ChildClass();
$obj->test1();
$obj->test2();
?>

Kết quả

parent method overridden
trait method overridden

Trait với Interface

Có thể có class implement interface, extend parent class và dùng trait cùng lúc:

<?php
trait MyTrait {
    public function test1() {
        echo "test1 method in trait1\n";
    }
}
class MyClass {
    public function test2() {
        echo "test2 method in parent class\n";
    }
}
interface MyInterface {
    public function test3();
}
class TestClass extends MyClass implements MyInterface {
    use MyTrait;
    public function test3() {
        echo "implementation of test3 method\n";
    }
}
$obj = new TestClass();
$obj->test1();
$obj->test2();
$obj->test3();
?>

Kết quả

test1 method in trait1
test2 method in parent class
implementation of test3 method

Conflict resolution (Giải quyết xung đột)

Nếu class dùng hai trait có method trùng tên, xung đột giải quyết bằng scope resolution operator (::) và từ khóa insteadof.

<?php
trait Trait1 {
    public function test1() { echo "test1 method in trait1\n"; }
    public function test2() { echo "test2 method in trait1\n"; }
}
trait Trait2 {
    public function test1() { echo "test1 method in trait2\n"; }
    public function test2() { echo "test2 method in trait2\n"; }
}
class TestClass {
    use Trait1, Trait2 {
        Trait1::test1 insteadof Trait2;
        Trait2::test2 insteadof Trait1;
    }
}
$obj = new TestClass();
$obj->test1();
$obj->test2();
?>

Kết quả

test1 method in trait1
test2 method in trait2