Hướng đối tượng và lập trình PHP phần 1
Bài đăng này đã không được cập nhật trong 3 năm
Giới thiệu
Vạn vật quanh chúng ta đang vận động không ngừng…Ngày ngày mặt trời vẫn mọc ở đằng Đông, rồi mặt trời lặn đằng Tây và mặt trăng cũng lên =)) ( có vẻ đi hơi xa rồi) .Tuy nhiên đơn thuần khi ta quan sát vạn vật tự nhiên, lập trình hướng đối tượng như một cách quan sát các đối tượng như thế. Rồi cố gắng nắm bắt những hành động cùng đặc tính của chúng và biểu diễn dưới dạng đối tượng ảo trong ngôn ngữ lập trình và triển khai một phần mềm bởi sử dụng các đối tượng khác nhau. Hướng đối tượng được áp dụng vào nhiều ngôn ngữ lập trình khác nhau đáng chú ý như: Java, C++, C#, Python, PHP, Ruby,... Bài này chúng ta cùng tìm hiểu về OOP và xem nó được thể hiện vào PHP như thế nào nhé.
Vấn đề
- Thế nào là lập trình hướng đối tượng?
- Các đặc điểm cơ bản quả lập trình hướng đối tượng là gì?
- Hướng đối tượ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ớiself::method()
.
Nội dung
1. Thế nào là lập trình hướng đối tượng?
Lập trình hướng đối tượng (tiếng Anh: Object-oriented programming, viết tắt: OOP
) là kỹ thuật lập trình nhằm vào sự tương tác của các đối tượng. Mỗi đối tượng có những thuộc tính (thông tin lưu trữ), những phương thức xác định chức năng của đối tượng. Bên cạnh đó, đối tượng có khả năng phát sinh ra các sự kiện khi thay đổi thông tin, thực hiện một chức năng hay khi đối tượng khác tác động vào. Tất cả những thuộc tính, phương thức và sự kiện tạo nên cấu trúc hướng đối tượng.
Tư tưởng: Tư tưởng của OOP
là xây dựng một chương trình dựa trên sự phối hợp hoạt động của các đối tượng. Một đối tượng bao gồm hai thành phần chính: thông tin lưu trữ và các thao tác xử lý.
2. Các đặc điểm cơ bản của lập trình hướng đối tượng là gì?
Lập trình hướng đối tượng được biết tới với 4 tính chất cơ bản:
- Tính trừu tượng (Abstraction)
- Tính đóng gói (Encapsulation)
- Tính kế thừa (Inheritance)
- Tính đa hình (Polymorphism)
Tính trừu tượng:
Chúng ta thường nhầm lẫn giữa lớp (class
) và đối tượng (object
). Vì vậy chúng ta cần phải phân biệt:
Lớp là một tính chất trừu tượng Đối tượng là thể hiện cụ thể của lớp
Ví dụ: Bản thiết kế nhà là lớp, ngôi nhà được xây dựng trên bản thiết kế là đối tượng.
Tính đóng gói:
Cơ chế đóng gói là phương thức tốt để thực hiện cơ chế che dấu thông tin so với các ngôn ngữ lập trình cấu trúc.
- Các dữ liệu và phương thức có liên quan với nhau được đóng gói thành các lớp để tiện cho việc quản lý và sử dụng.
- Ngoài ra, đóng gói còn để che giấu một số thông tin và chi tiết cài đặt nội bộ để bên ngoài không thể nhìn thấy.
Các mức truy cập:
- Public: Cho phép truy cập và sử dụng đến các phương thức cũng như thuộc tính ở phạm vi trong, ngoài
class
và nó hỗ trợ sự kế thừa. - Private: Chỉ cho phép truy cập và sử dụng đến các phương thức cũng như thuộc tính ở phạm vi trong
class
. - Protected: Cho phép truy cập và sử dụng đến các phương thức cũng như thuộc tính ở phạm vi trong
class
và nó hỗ trợ sự kế thừa.
Tính kế thừa: Là khả năng cho phép ta xây dựng một lớp mới dựa trên các định nghĩa của một lớp đã có. Lớp đã có gọi là lớp cha, lớp phát sinh gọi là lớp con và đương nhiên lớp con kế thừa tất cả các thành phần của lớp cha mở rộng các thành phần kế thừa cũng như bổ sung thêm các thành phần mới Ví dụ: Ta có lớp người là lớp cha và lớp con là lập trình viên. Đương nhiên lập trình viên kế thừa hết các đặc tính của con người đúng không nào =))
Tính đa hình:
Tính đa hình được thể hiện qua việc viết lại các method (hàm) từ class cha thông qua class kế thừa nó hoặc việc triển khai các interface
.
Hoặc có thể được hiểu là Lớp Con sẽ viết lại những phương thức ở lớp cha (overwrite).
Ví dụ: Hành động ăn ở các loài động vật hoàn toàn khác nhau như: con heo ăn cám, hổ ăn thịt, con người thì ... ăn hết =)).
3. Hướng đối tượng được thể hiện như thế nào trong PHP
Tính trừu tượng:
- Tính trừu tượng (abstraction) 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.
- Trong PHP: Tính trừu tượng được thể hiện qua lớp giao diện (Interface) và lớp trừu tượng(abstract).
abstract class AbstractClass
{
// Our abstract method only needs to define the required arguments
abstract protected function prefixName($name);
}
class ConcreteClass extends AbstractClass
{
// Our child class may define optional arguments not in the parent's signature
public function prefixName($name, $separator = ".") {
if ($name == "Pacman") {
$prefix = "Mr";
} elseif ($name == "Pacwoman") {
$prefix = "Mrs";
} else {
$prefix = "";
}
return "{$prefix}{$separator} {$name}";
}
}
$class = new ConcreteClass;
echo $class->prefixName("Pacman"), "\n";
echo $class->prefixName("Pacwoman"), "\n";
Kết quả của ví dụ:
Mr. Pacman Mrs. Pacwoman
Tính đóng gói: Trong PHP việc đóng gói được thực hiện nhờ sử dụng các từ khoá public, private và protected:
- Public: Cho phép truy cập (và thay đổi giá trị) của thuộc tính và phương thức ở mọi phạm vi.
- Private: Chỉ cho phép truy cập (hay thay đổi) giá trị của thuộc tính và phương thức ở phạm vi của đối tượng (hoặc lớp).
- Protected: Chỉ cho phép truy cập (hay thay đổi) giá trị của thuộc tính và phương thức ở phạm vi của đối tượng con (hoặc lớp con).
Tính kế thừa:
Con người | Lập trình viên |
---|---|
Thuộc tính: Mắt, mũi, miệng,... | Thuộc tính: Mắt, mũi, miệng, bằng cấp, chứng chỉ,... |
Phương thức: Ăn, ngủ, chơi game,... | Phương thức: Ăn, ngủ, chơi game,... |
Nhìn vào bảng trên ta thấy 2 đối tượng Con người và Lập trình viên có những đặc điểm chung và riêng. Ta có thể thấy rằng Lập trình viên có thể kế thừa nhưng đặc điểm và phương thức của Con người. Hình trên sẽ được viết lại dưới dạng kế thừa như sau:
// Lớp Cha
class Person
{
// Thuộc Tính
var $mat = '';
var $mui = '';
var $mieng = '';
// Hàm, phương thức
function eat(){
// lệnh
}
function sleep(){
// lệnh
}
function playGame(){
// lệnh
}
}
// Lớp Con
class Programmer extends Person {
// Tất cả các thuộc tính khác đều kế thừa từ cha
// nên không cần viết lại
// chỉ riêng thuộc tính này là cha ko có nên ta phải khai báo
var $qualifications = '';
var $certificate = '';
// Tất cả các hàm, phương thức đều kế thừa từ cha
// nên không cần viết lại
}
Tính đa hình: Trong PHP đa hình được hiểu là Lớp Con sẽ viết lại những phương thức ở Lớp Cha (overwrite). Tiếp tục ví dụ về hành động ăn của các loài động vật.
// Lớp Cha
class Animal
{
// Động Vật Ăn
public function eat()
{
echo 'Động Vật Đang Ăn';
}
}
// Lớp Con
class Pig extends Animal
{
public function eat()
{
parent::eat();
echo 'Con Heo Đang Ăn Cám';
}
}
// Khai Báo Lớp con
$pig = new Pig();
// Gọi Hàm Ăn Trong Lớp Pig
$pig->eat();
Ta thấy lớp Pig
đã định nghĩa lại hàm eat()
của lớp Animal nên khi gọi đến hàm eat()
sẽ được tính là gọi ở lớp Pig
, nếu trong lớp Pig
không có hàm eat()
thì lúc này mới tính ở class Animal
.
4. Sự khác biệt giữa Abstract Class và Interface
Chắc chắn rằng khi làm việc với lập trình hướng đối tương (OOP
) có hai khái niệm mà các bạn đã thấy đó là Abstract
và Interface
. Tuy nhiên nhiên đa số có vẻ còn khá mơ hồ khi phân biệt chúng. Và đơn giản hai khái niệm được định nghĩa như sau:
- Abstract class: Lớp trừu tượng đơn giản được xem như một class cha 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 đó.
- 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 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).
Bất kỳ lớp nào sử dụng lớp interface đều phải định nghĩa các phương thức đã khai báo ở lớp interface
, nếu cố tình không khai báo thì PHP sẽ báo lỗi, để sử dụng lớp interface
bạn chỉ việc khai báo với từ khóa implements
và một lớp có thể sử dụng nhiều interface
cũng như vừa có thể kế thừa từ lớp khác và đồng thời sử dụng interface
. Ví dụ:
interface a{
public function pa();
}
interface b{
public function pb();
}
class c{
public function pc(){
echo 'phuong thuc pc cua lop c';
}
}
class d extends c implements a,b{
public function pa(){
echo 'phuong thuc pa duoc khai bao interface';
}
public function pb(){
echo 'phuong thuc pb duoc khai bao interface';
}
public function pd(){
echo 'phuong thuc pc cua lop d';
}
}
$s = new d();
$s->pc();
Trong lớp abstract
chứa các phương thức abstract chúng cũng rỗng giống như phương thức trong interface
, vậy nên khi một lớp kế thừa từ lớp asbtract
thì bắt buộc phải định nghĩa phương thức đã khai báo ở lớp abstract
.
Một lớp abstract
khi sử dụng cũng như kế thừa bạn khai báo với từ khóa "extends"
điều này không giống như interface
. Ví dụ:
abstract class a{
protected $vara = 'pa2() cua lop a';
abstract function pa();
protected function pa2(){
return $this->vara;
}
}
class b extends a{
public function pa(){
echo 'pa() duoc khai bao abtract o lop a';
}
public function pb(){
echo $this->pa2();
}
}
$s = new b();
$s->pb();
5. 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. Và cũng vì điều này mà khi sử dụng static trong chương trình thì nó sẽ chiếm nhiều tài nguyên hơn các thành phần thường.
Phân biệt cách dùng từ khoá static::method()
với self::method()
self::method()
tham chiếu đến hàm method tại thời điểm nó được định nghĩa.static::method()
tham chiếu đến hàm method tại thời điểm nó được gọi.
class A
{
public static function test()
{
echo 'a';
}
public static function run()
{
self::test(); // always a
static::test(); // depend on called class
}
}
class B extends A {
public static function test()
{
echo 'b';
}
}
A::run(); // output 'aa'
B::run(); // output 'ab'
Tóm tắt:
Self
: Truy xuất đến class khai báo nó.Static
: Truy xuất đến đối tượng hiện tại.
Kết luận
Qua bài viết, các bạn có thể đã hiểu được cơ bản về hướng đối tượng và việc thể hiện nó trong PHP rồi đúng không nhỉ =)). Các bạn hãy theo dõi phần tiếp theo tại đây: https://viblo.asia/p/huong-doi-tuong-va-lap-trinh-php-phan-2-1Je5E8gYlnL
All rights reserved