PHP / Класс ба объект

Класс ба объект

Одоо хүртэл бид PHP-н процедурал хэв маягаар код бичсэн — функцуудыг дараалан дуудах хэлбэрээр. Гэхдээ том програм бичих үед код нь хурдан эмх замбараагүй болдог. Объект хандалтат програмчлал (Object-Oriented Programming, OOP) нь энэ асуудлыг шийддэг — холбогдох өгөгдөл ба функцуудыг нэг дор класс-д цуглуулдаг. PHP-д OOP маш хүчтэй дэмжигдсэн бөгөөд Laravel зэрэг фреймворкууд бүхэлдээ OOP-д суурилдаг.

Класс гэж юу вэ?

Класс бол загвар (blueprint) юм. Жишээлбэл, "Машин" класс нь бүх машины нийтлэг шинж чанар (өнгө, марк, хурд) болон үйлдлүүдийг (явах, зогсох) тодорхойлдог. Объект бол тэр загвараар үүсгэсэн тодорхой жишээ — "Улаан Toyota" бол Машин классаас үүсгэсэн объект:

php
<?php
// Класс тодорхойлох
class Машин {
    // Шинж чанар (property)
    public string $марк;
    public string $өнгө;
    public int $хурд = 0;

    // Арга (method)
    public function явах(int $хурдыгНэм): void {
        $this->хурд += $хурдыгНэм;
        echo $this->марк . " " . $this->хурд . " км/цагаар явж байна.\n";
    }

    public function зогсох(): void {
        $this->хурд = 0;
        echo $this->марк . " зогслоо.\n";
    }
}

// Объект үүсгэх
$миний_машин = new Машин();
$миний_машин->марк = "Toyota";
$миний_машин->өнгө = "Улаан";

$миний_машин->явах(60);  // Toyota 60 км/цагаар явж байна.
$миний_машин->зогсох();  // Toyota зогслоо.
?>

$this нь "энэ объект" гэсэн утгатай — класс дотроос өөрийн шинж чанарт хандахдаа ашигладаг.

Constructor — объект үүсгэхэд автоматаар ажилладаг

__construct() арга нь new гэсэн үгээр объект үүсгэх үед шууд дуудагддаг. Шинж чанаруудыг эхлүүлэхэд тохиромжтой:

php
<?php
class Хэрэглэгч {
    public string $нэр;
    public string $имэйл;
    public int $нас;

    public function __construct(string $нэр, string $имэйл, int $нас) {
        $this->нэр   = $нэр;
        $this->имэйл = $имэйл;
        $this->нас   = $нас;
    }

    public function танилцуулга(): string {
        return "{$this->нэр} ({$this->нас} нас) — {$this->имэйл}";
    }
}

// Объект үүсгэхдээ шууд утга дамжуулна
$хэрэглэгч1 = new Хэрэглэгч("Болд", "bold@example.mn", 25);
$хэрэглэгч2 = new Хэрэглэгч("Сарнай", "sarnai@example.mn", 22);

echo $хэрэглэгч1->танилцуулга(); // Болд (25 нас) — bold@example.mn
echo $хэрэглэгч2->танилцуулга(); // Сарнай (22 нас) — sarnai@example.mn
?>

Constructor нь маягтын шалгалттай адилхан — зөв утга дамжуулахыг хангаж, объектыг зөв эхлүүлдэг.

Хандалтын удирдлага: public, private, protected

Шинж чанар болон аргад хандах эрхийг зохицуулдаг гурван түлхүүр үг байдаг:

php
<?php
class Дансны_мэдээлэл {
    public string $нэр;          // хаанаас ч хандаж болно
    private float $үлдэгдэл;    // зөвхөн класс дотроос
    protected string $валют;    // класс болон хүүхэд классаас

    public function __construct(string $нэр, float $үлдэгдэл) {
        $this->нэр      = $нэр;
        $this->үлдэгдэл = $үлдэгдэл;
        $this->валют    = "MNT";
    }

    // private шинж чанарыг гаднаас уншуулах getter арга
    public function үлдэгдэлАвах(): float {
        return $this->үлдэгдэл;
    }

    // private шинж чанарыг гаднаас өөрчлүүлэх setter арга
    public function мөнгөОруулах(float $дүн): void {
        if ($дүн > 0) {
            $this->үлдэгдэл += $дүн;
        }
    }
}

$данс = new Дансны_мэдээлэл("Болд", 100000.0);

echo $данс->нэр;              // Болд — ажиллана (public)
echo $данс->үлдэгдэлАвах();  // 100000 — getter-ээр хандна

// echo $данс->үлдэгдэл;     // АЛДАА — private шинж чанарт шууд хандаж болохгүй

$данс->мөнгөОруулах(50000);
echo $данс->үлдэгдэлАвах();  // 150000
?>

private ашигласнаар гаднаас буруу өгөгдөл оруулж объектыг "эвдэж" чадахгүй болно — энэ бол OOP-н гол давуу талуудын нэг.

Олон объект үүсгэх

Нэг классаас хэдэн ч объект үүсгэж болно — бүгд тусдаа шинж чанартай:

php
<?php
class Бүтээгдэхүүн {
    public function __construct(
        public string $нэр,
        public float  $үнэ,
        public int    $тоо
    ) {}

    public function нийтДүн(): float {
        return $this->үнэ * $this->тоо;
    }
}

$барааны_жагсаалт = [
    new Бүтээгдэхүүн("Гар утас",  1_200_000, 2),
    new Бүтээгдэхүүн("Чихэвч",      45_000, 5),
    new Бүтээгдэхүүн("Цэнэглэгч",   25_000, 3),
];

$нийт = 0;
foreach ($барааны_жагсаалт as $бараа) {
    echo $бараа->нэр . ": " . number_format($бараа->нийтДүн()) . "₮\n";
    $нийт += $бараа->нийтДүн();
}

echo "Нийт дүн: " . number_format($нийт) . "₮";
?>

PHP 8+ дээр constructor дотор public гэж зарлахад шинж чанарыг тусад нь бичихгүйгээр богино хэлбэрээр бичиж болдог.

Дараагийн хичээлд:

Constructor болон destructor-ийн дэлгэрэнгүй ажиллагааг судална. Объект устах үед автоматаар ажилладаг __destruct() аргыг болон constructor-н ахисан хэрэглээг жишээгээр үзнэ.