Hướng dẫn dùng extends trong PHP

Cách kế thừa một lớp trong lập trình hướng đối tượng PHP

Khái niệm kế thừa là gì ?

– Đối với lập trình hướng đối tượng trong PHP, khái niệm “kế thừa” dùng để ám chỉ việc một lớp được dẫn xuất từ một lớp khác.

– Lớp được dẫn xuất từ lớp khác thì được gọi là “lớp con”, nó sẽ thừa hưởng tất cả các thuộc tính và phương thức (thuộc loại public & protected) của lớp cha, ngoài ra thì lớp con có thể sở hữu các thuộc tính & phương thức của riêng nó.

– Một lớp con sẽ được khai báo bằng từ khóa extends với cú pháp như sau:

class TênLớpCon extends TênLớpCha{
	//some code
}

– Lớp SinhViên được kế thừa từ lớp CôngDân, cho nên nó sẽ thừa hưởng các thuộc tính & phương thức từ lớp CôngDân. Ngoài ra, lớp SinhViên còn có một phương thức riêng là message().

<?php
	class CongDan{
		public $name;
		public $year;
		public function __construct($input_name, $input_year){
			$this->name = $input_name;
			$this->year = $input_year;
		}
		public function intro(){
			echo "Tôi tên là {$this->name}, sinh năm {$this->year}";
		}
	}
	class SinhVien extends CongDan{
		public function message(){
			echo "Chào các bạn!<br>";
		}
	}
	$nhan = new SinhVien("Nguyễn Thành Nhân",1993);
	$nhan->message();
	$nhan->intro();
?>

Phạm vi truy cập protected

– Ở bài học trước thì tôi đã có giới thiệu sơ qua ba từ khóa public – protected – private dùng để xác định phạm vi truy cập của các thuộc tính
& phương thức. Trong đó, public và private đã được giải thích chi tiết thông qua các ví dụ, còn riêng protected thì chưa (bởi vì trong bài đó các bạn chưa biết khái niệm kế thừa)

– Cho nên, trong phần này tôi sẽ làm sơ qua hai ví dụ để các bạn hiểu rõ hơn về phạm vi truy cập protected.

<?php
	class CongDan{
		public $name;
		public $year;
		public function __construct($input_name, $input_year){
			$this->name = $input_name;
			$this->year = $input_year;
		}
		protected function intro(){
			echo "Tôi tên là {$this->name}, sinh năm {$this->year}";
		}
	}
	class SinhVien extends CongDan{
		public function message(){
			echo "Chào các bạn!<br>";
		}
	}
	$nhan = new SinhVien("Nguyễn Thành Nhân",1993);
	$nhan->message();
	$nhan->intro(); //ERROR (phương thức intro là protected, nó chỉ có thể được gọi bên trong lớp CongDan, hoặc được gọi bên trong các lớp được kế thừa từ lớp CongDan, điển hình như lớp SinhVien)
?>

<?php
	class CongDan{
		public $name;
		public $year;
		public function __construct($input_name, $input_year){
			$this->name = $input_name;
			$this->year = $input_year;
		}
		protected function intro(){
			echo "Tôi tên là {$this->name}, sinh năm {$this->year}";
		}
	}
	class SinhVien extends CongDan{
		public function message(){
			echo "Chào các bạn!<br>";
			$this->intro(); //OK (phương thức intro được gọi bên trong lớp SinhVien)
		}
	}
	$nhan = new SinhVien("Nguyễn Thành Nhân",1993);
	$nhan->message();
?>

Ghi đè phương thức

– Các phương thức được kế thừa từ lớp cha có thể được ghi đè bằng cách khai báo lại bên trong lớp con.

<?php
	class CongDan{
		public $name;
		public $year;
		public function __construct($input_name, $input_year){
			$this->name = $input_name;
			$this->year = $input_year;
		}
		protected function intro(){
			echo "Tôi tên là {$this->name}, sinh năm {$this->year}";
		}
	}
	class SinhVien extends CongDan{
		public $gender;
		public function __construct($input_name, $input_year, $input_gender){
			$this->name = $input_name;
			$this->year = $input_year;
			$this->gender = $input_gender;
		}
		public function intro(){
			echo "Tôi tên là {$this->name}, sinh năm {$this->year}, giới tính {$this->gender}";
		}
	}
	$nhan = new SinhVien("Nguyễn Thành Nhân",1993,"Nam");
	$nhan->intro();
?>

Từ khóa final

– Từ khóa final dùng để ngăn chặn việc kế thừa lớp, hoặc ngăn chặn việc ghi đè lên phương thức.

– Không lớp nào có thể kế thừa lớp CongDan (việc định nghĩa lớp SinhVien kế thừa lớp CongDan sẽ xảy ra lỗi)

<?php
	final class CongDan{
		public $name;
		public function __construct($input_name){
			$this->name = $input_name;
		}
		public function intro(){
			echo "Tôi tên là {$this->name}";
		}
	}
	class SinhVien extends CongDan{ //ERROR
		//some code
	}
?>

– Phương thức intro() sẽ không thể bị ghi đè bên trong các lớp con.

<?php
	class CongDan{
		public $name;
		public function __construct($input_name){
			$this->name = $input_name;
		}
		final public function intro(){
			echo "Tôi tên là {$this->name}";
		}
	}
	class SinhVien extends CongDan{
		public function intro(){ //ERROR
			echo "Chào các bạn, tôi tên là {$this->name}";	
		}
	}
?>