OOP - Khái niệm về lập trình hướng đối tượng

Hướng đối tượng là gì?

OOP (Object Oriented Programming) - lập trình hướng đối tượng không chỉ sử dụng các cú pháp viết code mới mà nó làm bạn thay đổi cách nghĩ về một vấn đề bài toán đặt ra. Khi sử dụng lập trình hướng thủ thục (Procedural programming), thì tập trung vào viết các hàm để thi hành trên dữ liệu. Còn lập trình hướng đối tượng tập trung vào tạo ra các đối tượng (object) trong đối tượng đó chứa dữ liệu và các hàm (phương thức). Một đối tượng chứa các đặc tính của đối tượng (dữ liệu) và ứng sử của đối tượng (các method - hàm).

Khi lập trình, ví dụ xử lý một quy trình - người dùng nhập dữ liệu vào form HTML, rồi gửi thông tin lên server web. Mã PHP có thể sẽ kiểm tra dữ liệu gửi đến, gửi email chứa dữ liệu đó cho quản trị, lưu trữ dữ liệu vào db ... Trong quy trình đó (hay bất kỳ chức năng nào của ứng dụng) đều biểu thị bởi các động từ như: kiểm tra, gửi email, lưu trữ ... và các danh từ như dữ liệu tên người dùng, địa chỉ email.

  • Lập trình hướng thủ tục - OP: tập trung vào các động từ - làm điều gì đó, sau đó làm gì đó, ...
  • Lập trình hướng đối tượng - OOP: tập trung vào các danh từ (dữ liệu) - cái gì đó giúp ứng dụng hoạt động

Một vài khái niệm cơ sở về OOP trong PHP

Dưới đây là một số khái niệm trong lập trình hướng đối tượng với PHP, các khái niệm này cũng có thể coi là nhưng đặc tính của lập trình OOP. Mỗi khái niệm bạn nắm bắt thông tin cơ bản rồi sau đó sẽ hiểu chi tiết nó trong các bài viết cụ thể phần sau.

Class - lớp

Lớp (class) là một kiểu dữ liệu do người dùng định nghĩa, trong lớp có chứa các hàm và dữ liệu của nó. Một lớp class là định nghĩa về đối tượng / sự việc tổng quát. Từ đó sử dụng để tạo ra các đối tượng (object) là một triển khai cụ thể. Xem chi tiết: Khai báo, tạo ra các lớp trong PHP

Object - Đối tượng

Object (đối tượng, instance) là một triển khai cụ thể dữ liệu được định nghĩa trong lớp. Ví dụ, kiểu lớp Student bạn khai báo có dữ liệu ten, tuoi. Dùng lớp Student để tạo ra đối tượng cụ thể như $sinhvienA (ten = A, tuoi 20), $sinhvienB (ten B, tuoi 21) ... Xem chi tiết tại: Đối tượng trong PHP

Module hóa ứng dụng

Một trong các triết lý của OOP đó là module hóa: chia ứng dụng ra thành nhiều phần nhỏ tách biệt. Ví dụ một website có rất nhiều thứ cần làm: tương tác với CSDL, gửi email, nhận lý dữ liệu gửi đến từ form, sinh mã HTML cho trang ... Thế thì mỗi thứ này, có thể phát triển riêng biệt gọi chúng là các module và nhiều khi chúng sẽ tương ứng với class. Bằng cách tách biết sự liên quan giữa các phần tử như vậy, giúp bạn phát triển, cập nhật, gỡ rối đơn giản hơn rất nhiều.

Tính kế thừa

Khi định nghĩa một lớp mới, bạn có thể kế thừa dữ liệu và phương thức từ một lớp khác (lớp cha parent), lớp mới tạo ra gọi là lớp con (child). Xem chi tiết về kế thừa tại: Kế thừa trong PHP

Trừu tượng hóa abstract

Trừu tượng trong OOP liên quan tới việc các lớp được định nghĩa rất chung - bao quát (chỉ đề cập đến các phương thức, dữ liệu cần thiết), điều khá khó hiểu với người mới. Ví dụ, thay vì thiết kế thẳng một lớp chuyên tương tác với CSDL MySQL, bạn lại thiết kế một lớp mà mọi loại CSDL đều cần có dữ liệu nào đó, đều cần có phương thức nào đó. Như vậy là đã trừu tượng hóa truy cập CSDL thông qua lớp trừu tượng. Từ lớp chung đó, khi cần dùng riêng cho MySQL bạn sẽ quá tải các hàm, có thể định nghĩa thêm một số đặc tính đặc thù là có thể sử dụng với MySQL, tương tự với các loại CSDL cụ thể khác.

Xem chi tiết tại: Lớp trừu tượng trong PHP

Tính đóng gói

Đóng gói cũng là một khái niệm cơ sở của OOP, toàn bộ dữ liệu cần thiết được chứa trong đối tượng, và do nội bộ đối tượng xử lý, biến đổi - dữ liệu và cách dùng dữ liệu này là không cần biết bởi đối tượng sử dụng. Có nghĩa nó là một hộp đen, không cần biết bên trong hoạt động ra sao mà chỉ quan tâm kết quả phản ứng của hộp đen đó với các yêu cầu.

Tính đa hình

Ứng xử của đối tượng khác nhau tùy ngữ cảnh sử dụng. Tính đa hình có thể được thể hiện qua triển khai giao diện interface, qua quá tải phương thức overloading (các phương thức cùng tên nhưng tham số khác nhau).

Hàm tạo, hàm hủy

Trong lớp (class) có phương thức đặc biệt, khởi chạy đầu tiên khi tạo đối tượng đó là hàm tạo. Hàm chạy khi đối tượng bị hủy - giải phóng khỏi bộ nhớ - gọi là hàm hủy. Xem chi tiết tại: Hàm tạo - Hàm Hủy

Trên đây là các khái niệm rất cơ bản, chúng được làm rõ qua các ví dụ cụ thể.

Tính kế thừa

Khi định nghĩa các lớp (lớp con) bạn có thể cho lớp đó kế thừa các đặc tính từ một lớp khác (gọi là lớp cha) bằng từ khóa extends.

 class Child extends Parent { 
     //..
  }

Khi định nghĩa lớp như vậy

  • Lớp con sẽ có tất cả các thành viên biến (thuộc tính) khai báo trong lớp cha
  • Lớp con sẽ có tất cả các thành viên hàm giống lớp cha, mặc định những hàm này làm việc giống với cách làm việc của lớp cha
  • Trong lớp con có thể thêm các thuộc tính riêng, các phương thức riêng hoặc định nghĩa lại (quá tải) phương thức cha

Quá tải hàm là định nghĩa hàm trùng tên với hàm của lớp cha, mục đích chính là định nghĩa lại hàm nào đó quả lớp cha. Ví dụ dưới là hàm play

Ví dụ tạo lớp cha Pet và lớp con DogCat kế thừa từ Pet

<?
class Pet {
    public $name;
    function __construct($pet_name) {
        $this->name = $pet_name;
    }
    function eat() {
        echo "<p>$this->name is eating.</p>";
        $this->play();
    }
    function sleep() {
        echo "<p>$this->name is sleeping.</p>";
    }
    function play() {
        echo "<p>$this->name is playing.</p>";
    }
}


class Cat extends Pet {
    function play() {
        echo "<p>$this->name is climbing.</p>";
    }
}



class Dog extends Pet {
    function play() {
        echo "<p>$this->name is fetching.</p>";
    }
}


$dog = new Dog('Satchel');
$cat = new Cat('Bucky');
$pet = new Pet('Rob');

$dog->eat();
$cat->eat();
$pet->eat();

$dog->sleep();
$cat->sleep();
$pet->sleep();

$dog->play();
$cat->play();
$pet->play();

?>

Giao diện - Interface

Interface nó cung cấp tên các hàm chung để triển khai mã. Có thể nói interface (giao diện) là bộ khung mẫu để triển khai mã.

Để tạo ra interface cách tạo tương tự như class với keyword là interface và phần thân các phương thức không phải định nghĩa. Tất cả các phương thức trong interface là public

Ví dụ về tạo một interface

<?php
    interface ILogger
    {
        public function log($message);
    }
?>

Như vậy bạn thấy interface chỉ có tên interface và tên các phương thức. Giờ một lớp triển khai mã theo giao diện này sẽ định nghĩa lớp với cách sử dụng từ khóa implements

<?php
    class ClassName implements InterfaceName1, InterfaceName2 
    {
         
    }
?>

Khi lớp triển khai theo giao diện nào thì tất cả các hàm của giao diện đó lớp phải định nghĩa code đầy đủ. Ví dụ triển khai giao diện ILogger

<?php  

class FileLogger implements ILogger{ 
	public function log($message){
		echo sprintf("Log %s to the file\n",$message);			 
	}
}


class DBLogger implements ILogger{
	public function log($message){
		echo sprintf("Log %s to the database\n",$message);
	}
}

Lớp trừu tượng

Phương thức trừu tượng(hàm) là hàm khai báo với từ khóa abstract, nó chỉ là tên phương thức không chứa mã triển khai. Hàm khai báo như sau:

    abstract public function abstractMethod();

Khi một lớp có ít nhất một hàm trừu tượng thì lớp đó được gọi là lớp trừu tượng và trong khai báo lớp cũng chỉ ra từ khóa abstract

    
<?php
abstract class abstractClass{
    abstract public function abstractMethod();
    //.. các phương thức - thuộc tính khác
}

Lớp trừu tượng trong PHP được dùng như một lớp mẫu, không được sử dụng trực tiếp mà phải triển khai kế thừa lớp trừu tượng và định nghĩa lại các hàm trừu tượng.

Ví dụ về lớp trừu tượng:

    
<?php
abstract class Person{
    protected $firstName;
    protected $lastName;

    public function __construct($firstName,$lastName){
        $this->firstName = $firstName;
        $this->lastName  = $lastName;
    }

    public function __toString(){
        return sprintf("%s, %s",$this->lastName, $this->firstName);
    }

    abstract public function getSalary();
} 
?>

Với lớp trừu tượng Person trên nếu dùng khởi tạo trực tiếp lớp như sau sẽ lỗi:

    $p = new Person('John','Doe');

Để sử dụng đúng, cần kế thừa lớp trừu tượng và định nghĩa lại hàm trừu tượng cần thiết:

     
<?php
 
class Employee extends Person{
	private $salary;
 
	public function __construct($firstName,$lastName,$salary){
		parent::__construct($firstName, $lastName);
		$this->salary = $salary;
	}
 
	public function getSalary(){
		return $salary;
	}
 
}

 
$e = new Employee('John','Doe',5000);
echo $e;

Đăng ký nhận bài viết mới