Өвлөлт (Inheritance)
Өвлөлт бол OOP-н хамгийн хүчтэй ойлголтуудын нэг. Өвлөлт нь нэг классын шинж чанар ба аргуудыг нөгөө класс авч хэрэглэх боломжийг олгодог. Эх класс (parent class) дахь нийтлэг кодыг дахин бичихгүйгээр хүүхэд класс (child class) шууд ашигладаг. Энэ нь кодын давтамжийг эрс багасгаж, засвар хийхэд хялбар болгодог — нэг газар өөрчилбөл бүх хүүхэд класс автоматаар шинэчлэгддэг.
extends — өвлөлт тодорхойлох
extends түлхүүр үгээр хүүхэд класс зарлана. Хүүхэд класс нь эх классын бүх public болон protected шинж чанар, аргыг шууд ашиглаж болно:
<?php
// Эх класс
class Амьтан {
public string $нэр;
public string $дуу;
public function __construct(string $нэр, string $дуу) {
$this->нэр = $нэр;
$this->дуу = $дуу;
}
public function дуугарах(): void {
echo "{$this->нэр}: {$this->дуу}!\n";
}
public function тайлбар(): string {
return "Би {$this->нэр} нэртэй амьтан.";
}
}
// Хүүхэд класс — Амьтан-аас өвлөнө
class Нохой extends Амьтан {
public string $үүлдэр;
public function __construct(string $нэр, string $үүлдэр) {
// Эх классын constructor-г дуудна
parent::__construct($нэр, "Хав хав");
$this->үүлдэр = $үүлдэр;
}
public function getнэх(): void {
echo "{$this->нэр} чиний гарыг долоов!\n";
}
}
$нохой = new Нохой("Рекс", "Лабрадор");
$нохой->дуугарах(); // Рекс: Хав хав! — өвлөсөн арга
$нохой->getнэх(); // Рекс чиний гарыг долоов! — өөрийн арга
echo $нохой->тайлбар(); // Би Рекс нэртэй амьтан. — өвлөсөн арга
?>
parent::__construct() нь эх классын constructor-г дуудаж, шаардлагатай эхлүүлэлтийг хийлгэдэг. Үүнийг мартвал эх классын шинж чанарууд эхлүүлэгдэхгүй.
Аргыг override хийх
Хүүхэд класс нь эх классын аргыг дахин тодорхойлж, өөр хэлбэрээр ажиллуулж болно. Үүнийг override гэнэ:
<?php
class Дүрс {
public function талбай(): float {
return 0.0;
}
public function тайлбар(): void {
echo get_class($this) . " талбай: " . $this->талбай() . "\n";
}
}
class Тойрог extends Дүрс {
public function __construct(private float $радиус) {}
// талбай() аргыг override хийнэ
public function талбай(): float {
return M_PI * $this->радиус ** 2;
}
}
class Тэгш_өнцөгт extends Дүрс {
public function __construct(
private float $өргөн,
private float $өндөр
) {}
// талбай() аргыг override хийнэ
public function талбай(): float {
return $this->өргөн * $this->өндөр;
}
}
$дүрсүүд = [
new Тойрог(5),
new Тэгш_өнцөгт(4, 6),
];
foreach ($дүрсүүд as $дүрс) {
$дүрс->тайлбар();
}
// Тойрог талбай: 78.54...
// Тэгш_өнцөгт талбай: 24
?>
get_class($this) нь объектын классын нэрийг буцаадаг — debugging-д маш хэрэгтэй.
parent:: — эх классын аргыг дуудах
Override хийсэн ч эх классын аргыг бүрэн орлуулахгүйгээр нэмэлт ажил хийлгэхэд parent:: ашигладаг:
<?php
class Ажилтан {
public function __construct(
public string $нэр,
public float $цалин
) {}
public function мэдээлэл(): string {
return "{$this->нэр} — {$this->цалин}₮";
}
}
class Менежер extends Ажилтан {
public function __construct(
string $нэр,
float $цалин,
public string $хэлтэс
) {
parent::__construct($нэр, $цалин);
}
// Эх классын мэдээлэл()-г өргөтгөнө
public function мэдээлэл(): string {
return parent::мэдээлэл() . " | Хэлтэс: {$this->хэлтэс}";
}
}
$ажилтан = new Ажилтан("Болд", 800_000);
$менежер = new Менежер("Сарнай", 1_500_000, "Техникийн");
echo $ажилтан->мэдээлэл(); // Болд — 800000₮
echo $менежер->мэдээлэл(); // Сарнай — 1500000₮ | Хэлтэс: Техникийн
?>
Өвлөлтийн гинж — олон түвшин
<?php
class Тээврийн_хэрэгсэл {
public function явах(): void {
echo "Явж байна...\n";
}
}
class Машин extends Тээврийн_хэрэгсэл {
public function хаалга_нээх(): void {
echo "Хаалга нэээнэ.\n";
}
}
class Цахилгаан_машин extends Машин {
public function цэнэглэх(): void {
echo "Цэнэглэж байна.\n";
}
}
$tesla = new Цахилгаан_машин();
$tesla->явах(); // Тээврийн_хэрэгсэл-ээс өвлөсөн
$tesla->хаалга_нээх(); // Машин-аас өвлөсөн
$tesla->цэнэглэх(); // Өөрийн арга
// instanceof шалгалт
echo ($tesla instanceof Машин) ? "Машин мөн\n" : "";
echo ($tesla instanceof Тээврийн_хэрэгсэл) ? "Тээврийн хэрэгсэл мөн\n" : "";
?>
instanceof нь объект тодорхой классын жишээ мөн эсэхийг шалгадаг — өвлөлтийн гинжийн аль ч түвшинд true буцаана.
final — өвлөлт хориглох
final гэж тэмдэглэсэн класс эсвэл аргыг өвлөх буюу override хийх боломжгүй:
<?php
final class Аюулгүй_тоо {
public function __construct(private int $утга) {}
public function авах(): int {
return $this->утга;
}
}
// class Хүүхэд extends Аюулгүй_тоо {} // АЛДАА — final класс өвлөж болохгүй
class Тооцоолол {
final public function нэмэх(int $а, int $б): int {
return $а + $б;
}
}
?>
Дараагийн хичээлд:
Interface ба abstract класс ойлголтуудыг судална. Өвлөлтөөс юугаараа ялгаатай болохыг, хэдэн interface хэрэгжүүлж болохыг, abstract арга хэрхэн ажилладагыг тайлбарлана.