Kamis, 10 August 2023

Cara Menggunakan Constructor Property Promotion di PHP

Dalam pengembangan perangkat lunak dengan PHP, ada beberapa perubahan signifikan dalam sintaks dan fungsionalitas yang diperkenalkan oleh versi PHP terbaru. Salah satu perubahan menarik adalah property promotion, sebuah fitur yang diperkenalkan di PHP 8.

Pemrograman Berorientasi Objek (OOP) telah menjadi bagian integral dalam pengembangan aplikasi modern. Dalam dunia PHP, PHP 8 memperkenalkan fitur yang sangat berguna dan mempermudah pembuatan dan inisialisasi objek dengan nama "Constructor Property Promotion".

Fitur ini menghadirkan cara baru yang lebih bersih dan efisien dalam mendefinisikan dan menginisialisasi properti pada objek. Artikel ini akan membahas secara mendalam tentang Constructor Property Promotion dalam PHP dan bagaimana cara menggunakannya.

Sebelum kita lanjut, saya sudah pernah membuat artikel mengenai Pemrograman Berorientasi Objek (OOP) pada artikel sebelumnya dan yang akan kita bahas ini merupakan bagian dari Pemrograman Berorientasi Objek (OOP). Anda dapat membacanya disini .

Apa itu Constructor Property Promotion?

Constructor Property Promotion adalah fitur yang diperkenalkan dalam PHP 8 yang memungkinkan pengembang untuk mendefinisikan dan menginisialisasi properti objek langsung dalam parameter konstruktor. Sebelumnya, untuk mendeklarasikan dan menginisialisasi properti pada sebuah kelas, Anda harus melakukannya dengan cara manual di dalam konstruktor. Namun, dengan Constructor Property Promotion, Anda dapat melakukannya secara langsung dalam deklarasi parameter konstruktor, mengurangi boilerplate code yang tidak perlu.

Seringkali, kita menemukan diri kita menulis kode boilerplate yang berlebihan ketika menginisialisasi objek-objek sederhana. PHP 8 Constructor Property Promotion hadir untuk mengatasi masalah ini dengan menggabungkan deklarasi properti kelas, definisi konstruktor, dan penugasan nilai properti menjadi satu dalam daftar parameter konstruktor.

Mari kita lihat contoh sederhana untuk memahami bagaimana fitur ini berfungsi:

src/Customer.php
class Customer
{
    public function __construct(
        public string $name, 
        public string $email, 
        public DateTimeImmutable $birth_date,
    ) {}
}

Dalam contoh ini, kita memiliki kelas Customer yang memiliki tiga properti: name, email, dan birth_date. Dalam konstruktor, kita dapat langsung mendefinisikan properti-properti ini dengan menggunakan fitur Constructor Property Promotion. Ini menghilangkan kebutuhan untuk mendeklarasikan properti secara terpisah dan menginisialisasi mereka dalam konstruktor.

Sebagai perbandingan, inilah bagaimana kita biasanya melakukannya dalam PHP sebelumnya:

src/Customer.php
class Customer
{
    public string $name;
    public string $email;
    public DateTimeImmutable $birth_date;

    public function __construct(
        string $name, 
        string $email, 
        DateTimeImmutable $birth_date
    ) {
        $this->name = $name;
        $this->email = $email;
        $this->birth_date = $birth_date;
    }
}

Dengan Constructor Property Promotion, kode menjadi lebih singkat dan mudah dibaca. Fitur ini mengurangi boilerplate code yang sering kali hanya mengulangi deklarasi dan inisialisasi properti.

Namun, ada beberapa hal penting yang perlu diperhatikan:

  • Constructor Property Promotion hanya bisa digunakan di dalam konstruktor.
  • Anda dapat menggabungkan penggunaan properti yang dipromosikan dengan properti biasa.
  • Fitur ini meningkatkan kejelasan kode Anda, tetapi perhatikan agar tidak mengorbankan keterbacaan dengan penggunaan berlebihan.

Dalam penutup, Constructor Property Promotion adalah fitur yang memudahkan pengembangan objek sederhana dalam PHP 8. Dengan mengurangi boilerplate code, pengembang dapat lebih fokus pada logika inti dan meningkatkan produktivitas. Namun, tetaplah mengikuti praktik-praktik terbaik dalam pengembangan perangkat lunak dan komunikasikan penggunaan fitur ini dengan tim Anda.

Cara Kerjanya

"Constructor Property Promotion" adalah fitur yang diperkenalkan di PHP 8.0 yang memungkinkan Anda untuk mendeklarasikan properti kelas dan sekaligus menginisialisasinya dalam konstruktor dengan sintaks yang lebih singkat dan lebih bersih. Ini adalah cara yang efisien untuk mengurangi boilerplate code dalam mendefinisikan dan menetapkan nilai properti.

Sebelum fitur ini, Anda mungkin mendeklarasikan dan menginisialisasi properti kelas seperti ini:

src/User.php
class User
{
    private string $name;
    private int $age;

    public function __construct(string $name, int $age)
    {
        $this->name = $name;
        $this->age = $age;
    }
}

Dengan Constructor Property Promotion, Anda dapat menyederhanakan kode di atas menjadi:

src/User.php
class User
{
    public function __construct(
        private string $name,
        private int $age
    ) {}
}

Properti kelas secara otomatis dideklarasikan dan diinisialisasi dalam konstruktor.

Modifikasi akses (seperti public, protected, atau private) bisa langsung ditambahkan di depan parameter konstruktor.

Nilai yang diteruskan ke konstruktor saat instansiasi objek secara otomatis akan diinisialisasi ke properti kelas yang sesuai.

Ini berarti bahwa pada contoh pertama, meskipun kita memberikan nilai default 'Jenriko' pada parameter $name, nilai ini sebenarnya diatur dalam konstruktor saat kita menugaskan nilai tersebut ke properti $name menggunakan $this->name = $name;.

Dengan demikian, fitur ini memungkinkan Anda menggabungkan deklarasi properti, definisi konstruktor, dan inisialisasi nilai properti ke dalam satu baris, membuat kode lebih efisien dan lebih mudah dibaca.

Properti yang Dipromosikan

Mari kita lihat apa yang dapat dan tidak dapat dilakukan oleh property promotion, ada beberapa hal yang cukup rumit yang perlu dijelaskan!

Hanya dalam Konstruktor

Properti promotion hanya dapat digunakan dalam konstruktor. Mungkin terlihat jelas, tetapi saya pikir ini penting untuk disebutkan, agar semuanya jelas.

Dalam bahasa yang lebih sederhana, property promotion hanya boleh digunakan di dalam metode konstruktor suatu kelas. Kita tidak dapat menggunakan fitur ini di luar konteks konstruktor. Ini berarti bahwa kita hanya dapat menginisialisasi dan mengatur nilai properti-properti ini ketika objek dibuat melalui konstruktor.

Tidak Boleh Duplikasi

Anda mungkin bertanya apakah Anda dapat mendeklarasikan parameter dengan nama yang sama sebagai properti di dalam kelas yang sama.

Misalnya, Anda mungkin bertanya apakah kode berikut ini sah:

src/User.php
class User
{
    private string $name;

    public function __construct(
        private string $name
    ) {}
}

Jawabannya adalah tidak, kode ini akan menghasilkan error. Properti $name tidak dapat dideklarasikan dua kali dalam kelas yang sama, bahkan jika satu di antaranya adalah dalam konteks Constructor Property Promotion.

Jika Anda ingin menggunakan Constructor Property Promotion, Anda harus menghapus deklarasi properti yang ada di luar konstruktor, seperti ini:

src/User.php
class User
{
    public function __construct(
        private string $name
    ) {}
}

Dengan cara ini, kode Anda akan sah, dan properti $name akan dideklarasikan dan diinisialisasi menggunakan fitur Constructor Property Promotion, tanpa perlu mendeklarasikannya lagi di luar konstruktor.

Haruskah property ini menggunakan tipe?

Dalam hal ini, tentu untuk mendeklarasikan properti tanpa tipe data sepenuhnya sah dan diperbolehkan.

Perhatikan kode berikut ini:

src/User.php
class User
{
    public function __construct(
        private $name,
        private $age
    ) {}
}

Properti $name dan $age dalam contoh ini dideklarasikan tanpa tipe data, dan ini adalah penulisan yang benar dan diperbolehkan dalam PHP.

FYI Penggunaan tipe data dalam mendeklarasikan properti, parameter, termasuk juga return types dalam PHP (dan bahasa pemrograman lainnya) umumnya sangat direkomendasikan.

Nilai Default Sederhana

Properti yang dipromosikan dapat memiliki nilai default, tetapi ekspresi seperti new ... tidak diizinkan.

Contoh:

src/User.php
public function __construct(
    public string $name = 'Jenriko',
    public DateTimeImmutable $date = new DateTimeImmutable(),
) {}

Dalam contoh di atas, kita memiliki metode konstruktor dengan dua property promotion, yaitu $name dan $date. Properti $name memiliki nilai default 'Jenriko', yang akan digunakan jika tidak ada nilai yang diberikan saat pembuatan objek.

Namun, properti $date memiliki nilai default berupa new DateTimeImmutable(). Sayangnya, ekspresi seperti new DateTimeImmutable() tidak diperbolehkan sebagai nilai default. Ini berarti kita tidak dapat langsung menggunakan objek baru yang diinisialisasi di dalam nilai default property promotion. Jika Anda perlu memberikan nilai default yang rumit atau objek baru, sebaiknya lakukan inisialisasi di dalam konstruktor.

Menggabungkan Property Promotion dan Properti Biasa

Dengan Constructor Property Promotion, kita dapat mendeklarasikan dan menginisialisasi properti dalam satu baris dalam daftar parameter konstruktor, seperti contoh berikut:

src/MyClass.php
class MyClass
{
    public function __construct(
        public string $a,
        public string $b,
    ) {}
}

Namun, pertanyaannya adalah, bagaimana jika kita ingin menggabungkan properti yang dipromosikan dengan properti biasa? Jawabannya adalah: kita bisa melakukannya seperti contoh berikut:

src/MyClass.php
class MyClass
{
    public string $b;

    public function __construct(
        public string $a,
        string $b,
    ) {
        $this->b = $b;
    }
}

Pada contoh ini, kita mendeklarasikan properti biasa $b di luar daftar parameter konstruktor. Kemudian, dalam konstruktor, kita menginisialisasi nilai properti $b menggunakan nilai dari parameter konstruktor yang juga bernama $b. Di sisi lain, properti $a menggunakan fitur Constructor Property Promotion, yang memungkinkan kita untuk mendeklarasikan dan menginisialisasi nilai properti dalam satu baris. Pertimbangan dalam Mengkombinasikan Properti

Meskipun Anda memiliki fleksibilitas untuk menggabungkan properti yang dipromosikan dengan properti biasa, penting untuk tetap mempertimbangkan kejelasan dan keterbacaan kode. Ketika Anda menggunakan kombinasi kedua sintaks ini, ada potensi untuk membuat kode menjadi lebih kompleks. Oleh karena itu, jika kombinasi tersebut mengakibatkan kode menjadi kurang jelas atau lebih sulit dipahami, lebih baik untuk menggunakan pendekatan konstruktor biasa dengan penugasan manual properti.

Atribut

Sama seperti blok dokumen, atribut diperbolehkan pada property promotion. Saat ditranspilasi, atribut akan ada baik pada parameter konstruktor maupun pada properti kelas.

Contoh:

src/MyClass.php
class MyClass
{
    public function __construct(
        #[MyAttribute]
        public $a,  
    ) {}
}

Akan ditranspilasi menjadi:

src/MyClass.php
class MyClass 
{
    #[MyAttribute]
    public $a;
 
    public function __construct(
        #[MyAttribute]
        $a,
    ) {
        $this->a = $a;
    }
}

Dalam contoh di atas, kita memiliki kelas MyClass dengan property promotion $a. Yang menarik adalah penggunaan atribut pada properti tersebut. Pada saat ditranspilasi, atribut akan tetap ada pada parameter konstruktor dan juga pada properti kelas itu sendiri.

Fitur ini berguna ketika Anda ingin memberikan informasi tambahan atau metadata pada property promotion. Misalnya, Anda bisa menggunakan atribut untuk memberi tahu bahwa properti ini harus diperlakukan secara khusus atau memiliki penggunaan tertentu dalam konteks tertentu.

Tidak Diizinkan dalam Konstruktor Abstrak

Meskipun mungkin tidak banyak yang tahu tentang konstruktor abstrak, tetapi ada hal yang perlu dijelaskan. Property promotion tidak diizinkan digunakan dalam konstruktor abstrak.

Contoh:

src/Kupa.php
abstract class Kupa
{
    abstract public function __construct(
        public string $popol,
    ) {}
}

Pada contoh di atas, kita memiliki kelas abstrak Kupa dengan sebuah konstruktor abstrak yang memiliki properti yang dipromosikan $popol. Namun, PHP tidak mengizinkan penggunaan property promotion dalam konstruktor abstrak.

Ini berarti Anda tidak dapat menggunakan property promotion dalam konstruktor abstrak, karena konstruktor abstrak sendiri memiliki aturan dan karakteristik tertentu yang berbeda dari konstruktor biasa.

Diizinkan dalam Trait

Di sisi lain, property promotion diizinkan dalam trait. Hal ini masuk akal, karena sintaks yang di-transpile juga valid dalam trait.

Contoh:

src/Traits/MyTrait.php
trait MyTrait
{
    public function __construct(
        public string $a,
    ) {}
}

Pada contoh di atas, kita memiliki trait MyTrait dengan sebuah konstruktor yang memiliki property promotion yaitu $a. Fitur property promotion dapat digunakan dalam trait, karena sintaks yang dihasilkan dari transpilasi juga dapat diterapkan dalam trait.

Ini memberikan fleksibilitas dalam menggunakan fitur property promotion dalam berbagai konteks pengembangan, termasuk dalam trait.

Tidak Mendukung var

Pada masa lalu, pengembang PHP yang lebih berpengalaman mungkin telah menggunakan var untuk mendeklarasikan variabel kelas. Namun, dalam fitur constructor promotion, penggunaan var tidak diizinkan. Hanya kata kunci public, protected, dan private yang valid.

Contoh:

public function __construct(var string $a) {}

Pada contoh di atas, kita memiliki konstruktor dengan variabel yang dideklarasikan menggunakan var. Namun, dalam fitur constructor promotion, penggunaan var tidak diizinkan. Anda hanya dapat menggunakan kata kunci public, protected, atau private untuk mendeklarasikan visibilitas properti.

Ini menunjukkan perubahan dalam praktik terbaik pengkodean dan mengingatkan bahwa dalam pengembangan PHP yang lebih modern, penting untuk mengikuti standar baru yang diperkenalkan dalam fitur-fitur terbaru.

Parameter Variadic Tidak Dapat Dipromosikan

Karena Anda tidak dapat mengonversi menjadi tipe yang merupakan array dari tipe, maka tidak mungkin untuk mempromosikan parameter variadic.

Contoh:

public function __construct(
    public string ...$a,
) {}

Pada contoh di atas, kita memiliki konstruktor dengan parameter variadic yang di-promosikan. Namun, dalam fitur constructor promotion, penggunaan parameter variadic tidak diizinkan. Ini karena dalam constructor promotion, Anda tidak dapat mengubah tipe variadic menjadi tipe array.

Fitur ini memberikan batasan pada penggunaan parameter variadic dalam constructor promotion, dan ini menjadi pengingat bahwa ada batasan-batasan tertentu dalam fitur ini.

Pewarisan (Inheritance)

Karena konstruktor dalam PHP tidak perlu mengikuti deklarasi konstruktor induknya, maka tidak banyak yang perlu dijelaskan: pewarisan diperbolehkan. Namun, jika Anda perlu meneruskan properti dari konstruktor anak ke konstruktor induk, Anda harus melakukannya secara manual:

Contoh:

src/Hero.php
class Hero
{
    public function __construct(
        public $hanabi,
    ) {}
}

Kemudian diikuti dengan class Marksman seperti:

src/Marksman.php
class Marksman extends Hero
{
    public function __construct(
        $hanabi,
        public $popol,    
    ) {
        parent::__construct($hanabi);
    }
}

Dalam contoh di atas, kelas Marksman mewarisi dari kelas Hero. Konstruktor di kelas Marksman memiliki parameter $hanabi dan properti yang dipromosikan $popol. Namun, jika Anda perlu meneruskan nilai properti $hanabi ke konstruktor kelas induk Hero, Anda perlu melakukannya secara manual menggunakan parent::__construct($hanabi).

Ini mengingatkan bahwa dalam pewarisan, konstruktor di kelas anak tidak secara otomatis menerima semua parameter dari konstruktor kelas induk, terutama jika ada properti yang dipromosikan yang perlu diperhatikan.

Manfaat Property Promotion

Property promotion memberikan beberapa manfaat dalam pengembangan perangkat lunak PHP:

  • Mengurangi Boilerplate Code : Property promotion menghilangkan langkah-langkah redundan dalam mendeklarasikan dan menginisialisasi properti secara terpisah.
  • Kode Lebih Bersih : Property promotion membuat kode lebih ringkas dan mudah dibaca, karena deklarasi dan inisialisasi properti digabungkan dalam satu baris kode.
  • Meningkatkan Produktivitas: Dengan mengurangi boilerplate code, pengembang dapat fokus pada logika bisnis inti daripada menulis kode repetitif.

Kesimpulan

Property promotion adalah fitur yang bermanfaat dalam PHP 8 yang mengubah cara kita mendeklarasikan dan menginisialisasi properti dalam kelas.

Dengan menggabungkan deklarasi properti dan inisialisasi dalam parameter konstruktor, property promotion membuat kode lebih bersih, ringkas, dan mudah dibaca. Ini adalah salah satu langkah menuju kode yang lebih efisien dan produktif dalam pengembangan aplikasi PHP.

Dengan memahami konsep dan manfaat property promotion, pengembang dapat memanfaatkannya dalam proyek-proyek mereka untuk meningkatkan kualitas dan keterbacaan kode.

Semoga artikel ini bermanfaat saya Jenriko dan sampai jumpa di artikel selanjutnya.