Phân Biệt Sự Khác Nhau Giữa Interface Và Abstract Class Trong PHP

Nguyễn Đạt

Interface Là Gì

Interface định nghĩa tập hợp các method mà những class sử dụng interface sẽ cần phải triển khai (implement) các method này.

interface I_Test
{
    public function foo();
}

Với interface I_Test được định nghĩa như trên thì bắt buộc tất cả các class sử dụng interface này phải có method foo().

Trong PHP để sử dụng một interface bạn sử dụng từ khoá implements:

interface I_Test
{
    public function foo();
}

class A implements I_Test {
}

Nếu bạn lưu đoạn code trên vào một tập tin interface.php và chạy thì PHP sẽ báo lỗi như sau:

Fatal error: Class A contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (I_Test::foo) in...

Điều này là bởi vì class A sử dụng interface I_Test nên bắt buộc cần phải chứa bên trong nó method foo().

Bây giờ sửa lại class A lại giống đoạn code sau:

class A extends I_Test {
    public function foo();
}

Và chạy lại đoạn code thì bạn sẽ thấy PHP báo một lỗi khác:

Fatal error: Non-abstract method A::foo() must contain body in...

Điều này là bởi vì mặc dù class A đã có method foo nhưng method này lại không có nội dung. Nói cách khác class A mới chỉ khai báo chứ chưa thực sự việc triển khai method foo().

Bây giờ tiếp tục sửa lại class A lại giống đoạn code sau:

class A implements I_Test {
    public function foo {}
}

Lúc này khi chạy lại đoạn code được cập nhật bạn sẽ thấy PHP không còn báo lỗi nữa. Điều này là bởi vì mặc dù method foo() của class A đã có nội dung mặc dù nội dung của method là rỗng (khác với việc không tồn tại nội dung).

Một lưu ý quan trọng với interface nữa đó là các class khác nhau triển khai cùng một interface sẽ có thể có các cách triển khai các method của interface theo các cách khác nhau. Ví dụ sau hai class AB triển khai method foo của interface I_Test theo các cách khác nhau:

interface I_Test
{
    public function foo();
}

class A implements I_Test {
    public function foo() {
        echo "Hello World\n";
    }
}

class B implements I_Test {
    public function foo() {
        echo "Foo\n";
    }
}

$a = new A();
$a->foo();

$b = new B();
$b->foo();

Kết quả hiển thị:

Hello World
Foo

Chúng ta không thể tạo một instance object từ một interface. Đoạn code sau se không hợp lệ:

$iTest = new I_Test();

Abstract Class Là Gì

Abstract class định nghĩa tập hợp các method mà các class sử dụng (mở rộng) abstract class này cần phải triển khai (giống với interface), tuy nhiên khác với interface abstract class còn cung cấp thêm các method được triển khai cụ thể mà các class sử dụng nó có thể sử dụng mà không cần phải triển khai.

Ví dụ một abstract class như sau:

abstract class Abstract_Test
{
    abstract function sayHello();
}

Với cách định nghĩa class sử dụng từ khoá abstract như trên thì Abstract_Test là một abstract class. Trong đó method sayHello() là một method mà class nào sử dụng class Abstract_Test sẽ cần phải triển khai:

<?php
abstract class Abstract_Test
{
    abstract function sayHello();
}

class A extends Abstract_Test {
}

Khi chạy đoạn code trên PHP sẽ báo lỗi:

Fatal error: Class A contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Abstract_Test::sayHello) in ...

Điều này là bởi vì class A mở rộng Abstract_Test nhưng lại không khai báo method sayHello().

Bây giờ cập nhật lại code của class A như sau:

class A extends Abstract_Test {
    function sayHello();
}

Thì khi chạy đoạn code mới trên PHP vẫn báo lỗi:

Fatal error: Non-abstract method A::sayHello() must contain body in ...

Điều này là bởi vì giống như phần trước chúng ta đã tìm hiểu về interface thì method sayHello() mặc dù được khai báo nhưng chưa được triển khai. Sửa lại class A như sau và khi chạy lại code bạn sẽ không gặp phải lỗi:

class A extends Abstract_Test {
    function sayHello() {}
}

Một class abstract ngoài việc có thể chứa các method abstract thì còn có thể chứa các method non-abstract khác:

<?php
abstract class Abstract_Test
{
    abstract function sayHello();

    public function foo() {
        echo "Foo\n";
    }
}

Lúc này các class con mở rộng class Abstract_Test sẽ có thể sử dụng method foo() mà không cần định nghĩa nó:

class A extends Abstract_Test {
    function sayHello() {}
}

$a = new A();
$a->sayHello(); // Hiển thị rỗng
$a->foo(); // Hiển thị: Foo

Ngoài ra class A cũng có thể viết đè method foo() trong Abstract_Test nếu muốn:

class A extends Abstract_Test {
    function sayHello() {}
    public function foo() {
        echo "Foo Bar\n";
    }
}

$a = new A();
$a->sayHello(); // Hiển thị rỗng
$a->foo(); // Hiển thị: Foo Bar

Ngoài ra, chúng ta không thể tạo một instance từ một Abstract class. Đoạn code sau sẽ không hợp lệ:

$aTest = new Abstract_Test();

Cuối cùng trước khi kết thúc bài viết bạn cần lưu ý rằng một class khi được định nghĩa với ít nhất một abstract method (method với từ khoá abstract ở phía trước) sẽ cần phải được định nghĩa là một abstract class. Ví dụ class được định nghĩa như sau sẽ không hợp lệ:

<?php
class Abstract_Test {
    abstract function sayHello();
}

PHP sẽ báo lỗi:

Fatal error: Class Abstract_Test contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Abstract_Test::sayHello) in ...

Lỗi trên là do sayHello() đã được định nghĩa là abstract method nhưng class Abstract_Test lại không được định nghĩa là abstract class.

Thêm Phản Hồi

Bài Viết Liên Quan