Lập trình hướng đối tượng với PHP (Phần 1)
Bài đăng này đã không được cập nhật trong 5 năm
Mở đầu
Lập trình hướng đối tượng (gọi tắt là OOP - object-oriented programming) là một kĩ thuật lập trình hỗ trợ công nghệ đối tượng. Nếu như trước kia là các kiểu lập trình hướng thủ tục, hướng module,.. thì giờ đây thế giới đang ưu về sử dụng hướng đối tượng.Nếu như trước đây chúng ta lập trình với hướng thủ tục thì sẽ chia thành các hàm để xử lý, thì giờ đây khi sử dụng hướng đối tượng thì chúng ta sẽ chia ra thành các đối tượng để xử lý.
Bài viết dưới đây sẽ tập trung giải đáp các vấn đề sau:
- Các đặc điểm cơ bản của lập trình hướng đối tượng. Chúng được thể hiện như thế nào trong PHP.
- Sự khác biệt giữa Abstract Class và Interface.
- Thế nào là một hàm static. Phân biệt cách dùng từ khoá static::method() với self::method().
- Thế nào là Trait.
- Thế nào là Namespaces.
1. Các đặc điểm cơ bản của lập trình hướng đối tượng. Chúng được thể hiện như thế nào trong PHP.
Lập trình hướng đối tượng (OOP) có 4 đặc trưng cơ bản:
- Tính đóng gói (Encapsulation)
- Tính kế thừa (Inheritance)
- Tính đa hình (Polymorphism)
- Tính trừu tượng (Abstraction)
Tính đóng gói : Tính đóng gói được thể hiện qua việc các thuộc tính, phương thức được che giấu trong một lớp (class), nhằm mục đích kiểm soát quyền sử dụng, truy cập đến các thuộc tính, phương thức.
Tính đóng gói trong PHP được thể hiện thông qua việc sử dụng các từ khóa public, private, protected:
public: Cho phép sử dụng thuộc tính và phương thức củaclassở phạm vi trong, ngoàiclass, cácclasscon kế thừa từ đó đều có thể linh động sử dụng lại.private: Chỉ cho phép sử dụng trong phạm viclassđó.protected: Cho phép sử dụng ở phạm vi trongclasscha và cácclasskế thừa từclasscha.
Tính kế thừa: được thể hiện qua việc các class con kế thừa lại các phương thức, thuộc tính của class cha.
class Cha
{
public $quoctinh = 'Viet Nam';
public function noi()
{
echo "Noi tieng Viet Nam";
}
}
class Con extends Cha
{
public function __construct()
{
parent::noi();
}
}
new Con();
=> Noi tieng Viet Nam
Tính trừu tượng : trong lập trình hướng đối tượng giúp giảm sự phức tạp thông qua việc tập trung vào các đặc điểm trọng yếu hơn là đi sâu vào chi tiết. Như vậy khi tương tác với đối tượng chỉ cần quan tâm đến các thuộc tính, phương thức cần thiết. Chi tiết về nội dung không cần chú ý đến.
PHP có abstract class và interface để trừu tượng hóa các đối tượng.
interface Animal
{
public function noi();
}
class Dog implements Animal
{
public function noi()
{
echo "Go go go";
}
}
Tính đa hình: thể hiện qua việc các class con có thể viết lại các phương thức từ class cha, thông qua việc extends và implements
interface Animal
{
public function noi();
}
class Dog implements Animal
{
public function __construct()
{
$this->noi();
}
public function noi()
{
echo "Go go go";
}
}
class Cat implements Animal
{
public function __construct()
{
$this->noi();
}
public function noi()
{
echo "Meowwww";
}
}
new Dog();
=> Go go go
new Cat();
=> Meowwww
2. Sự khác biệt giữa Abstract Class và Interface.
Ở phần 1, chúng ta có nhắc tới 2 khái niệm abstract class và interface. Interfacevà Abstract classlà 2 khái niệm cơ bản trong lập trình OOP. Nhưng phân lớn mọi người cảm thấy mơ hồ và lẫn lộn 2 khái niệm này.
Abstract class: là một class trừu tượng cho tất cả các class có cùng bản chất.Do đó mỗi lớp dẫn xuất (lớp con) chỉ có thể kế thừa từ một lớp trừu tượng. Bên cạnh đó nó không cho phép tạo instance, nghĩa là sẽ không thể tạo được các đối tượng thuộc lớp đó.
abstract class Animal
{
public function noi()
{
echo "Noi...";
}
}
new Dog();
// => Báo lỗi
class Cat extends Animal
{
public function __construct()
{
$this->noi();
}
}
new Cat();
// => Noi...
Interface: Lớp này được xem như một mặt nạ cho tất cả các Class cùng cách thức hoạt động nhưng có thể khác nhau về bản chất. Từ đó lớp con dẫn xuất có thể kế thừa từ nhiều lớp Interface để bổ sung đầy đủ cách thức hoạt động của mình (đa kế thừa - Multiple inheritance).
interface A
{
public function method_a();
}
interface B
{
public function method_b();
}
class C implements A, B
{
public function __construct()
{
$this->noi();
}
public function method_b()
{
// TODO: Implement method_b() method.
}
public function method_a()
{
// TODO: Implement method_a() method.
}
}
3. Thế nào là một hàm static. Phân biệt cách dùng từ khoá static::method() với self::method().
Thế nào là một hàm static?: Hàm static là hàm có thể được gọi mà không cần một đối tượng của class đó. Static nó hoạt động như một biến toàn cục dù cho nó có được xử lý ở trong bất kỳ một file nào đi nữa (trong cùng một chương trình) thì nó đều lưu lại giá trị cuối cùng mà nó được thực hiện vào trong lớp.
public static function staticMethod()
{
//TODO
}
Việc thực thi hàm static trong class có thể thực hiện bằng lệnh:
static::staticMethod(),self::staticMethod()hoặc$this->staticMethod(), trong đóselfvàstaticlà đại diện củaclass, còn$thislà đại diện củaobject. Trong phương thứcstatickhông thể gọi phương thức hoặc thuộc tínhnon-static. Nhưng phương thứcnon-staticcó thể gọi phương thức hoặc thuộc tínhstatic. Bởi vì có thể hiểu đơn giản như sau:
- Phương thức
staticcó thể gọi ngay cả khi chưa khởi tạoobject, do đó nếu phương thứcstaticgọi đến một phương thứcnon-staticthì khi chưa khởi tạoobject, sẽ không có biến$this(là đại diện củaobject) để gọi đến phương thứcnon-static.- Đương nhiên phương thức
non-staticluôn luôn có thể gọi đến phương thứcstaticvì phương thứcstaticđã tồn tại ngay từ khi chạy chương trình, khiobjectchưa được khởi tạo.
Phân biệt cách dùng từ khoá static::method() với self::method():
static: đại diện cho chính đối tượng đang gọi đến phương thựcself: đại diện cho chính đối tượng khai báo nó.
class Person
{
public static function getSeflObject()
{
return new self;
}
public static function getStaticObject()
{
return new static;
}
}
class Girl extends Person
{
}
echo get_class(Girl::getSeflObject()); //Person
echo get_class(Girl::getStaticObject()); //Girl
4. Thế nào là Trait.
Traits hiểu đơn giản là một nhóm các methods mà bạn muốn include nó trong một class khác. Một Trait giống vớiabstract classkhông thể khởi tạo trên chính nó. Trait giảm bớt hạn chế của việc đơn kế thừa, cho phép chúng ta sử dụng lại một nhóm các phương thức trên class.
Một Trait đơn giản có thể là:
trait Sharable
{
public function share($item)
{
return 'share this item';
}
}
Chúng ta có thể sử dụng nó trong các class khác nhau như sau:
class Post
{
use Sharable;
}
class Comment
{
use Sharable;
}
Như vậy, khi bạn khởi tạo các đối tượng từ class Post, Comment, đối tượng đó sẽ có sẵn phương thức share().
Chúng ta có thể sử dụng nhiều Trait trong 1 class.
5. Thế nào là Namespaces.
Namespace giúp tạo ra một không gian tên cho hàm và lớp trong lập trình nói chung và trong PHP nói riêng. Với PHP, Namespaces được thiết kế để giải quyết hai vấn đề là tác giả của thư viện và các ứng dụng khi tái sử dụng lại các lớp và các hàm.
- Namespaces tránh việc tên hàm, tên lớp có thể trùng lặp, xung đột khi bạn tạo ra với các hàm, lớp, biến của PHP hay của bên thứ ba.
- Namespaces có khả năng tạo ra bí danh, rút ngắn cách đặt tên làm cho mã nguồn dễ đọc hiểu hơn.
namespace App\Controllers;
class NewsController
{
public function index()
{
echo __NAMESPACE__;
}
}
PHP Namespaces cung cấp cách để nhóm các class, interface, function, constant liên quan.
Kết luận
Qua bài viết, hy vọng các bạn đã hiểu được cơ bản về hướng đối tượng và việc thể hiện nó trong PHP, một vài khái niệm được sử dụng rộng rãi.
All rights reserved