Trait dalam OOP PHP - Ep. 15
Trait adalah suatu mekanisme dimana suatu class diizinkan untuk menggunakan kembali kode program (code reuse) yang berasal dari hirarki yang berbeda.
- 1. Cara membuat trait
- 2. Cara memakai trait
- 3. Multiple trait
- 4. Sebuah trait tersusun dari banyak trait
- 5. Trait tidak bisa dijadikan object (diinstansiasi)
- 6. Urutan prioritas method
- 7. Menangani konflik
- 8. Trait boleh memiliki property
- 9. Method dalam trait boleh mengakses method dan property dalam class yang memakainya meskipun private
- 10. Trait boleh memiliki abstract method
- 11. Merubah visibility method
Mari kita perhatikan contoh di bawah ini, saya buat tiga buah class:
class ApaKabar
{
public function apaKabar() {
return "Apa kabar?";
}
}
class SelamatPagi
{
public function selamatPagi() {
return "Selamat pagi?";
}
}
class Pesan
{
//
}
Jika kita menghendaki class Pesan
bisa menggunakan method apaKabar()
maka kita tinggal melakukan extends
ke class ApaKabar
seperti:
class ApaKabar
{
public function apaKabar() {
return "Apa kabar?";
}
}
class Pesan extends ApaKabar
{
//
}
$obj = new Pesan();
echo $obj->apaKabar();
Terus bagaimana jika kita ingin class Pesan
dapat menggunakan method apaKabar()
dan selamatPagi()
? class Pesan
meng-extends class ApaKabar
dan class SelamatPagi
? tentu ini tidak diperbolehkan oleh PHP, PHP hanya memperbolehkan satu parent class . Untuk itulah adanya Trait
1. Cara membuat trait
Sama seperti pembuatan class, hanya saja class
diganti dengan trait
// dengan keyword trait
trait ApaKabar
{
public function apaKabar() {
return "Apa kabar?";
}
}
2. Cara memakai trait
Cara memakai trait yaitu dengan menggunakan keyword use
dalam sebuah class dan diiringi nama trait
trait ApaKabar
{
public function apaKabar() {
return "Apa kabar?";
}
}
class Pesan
{
// menggunakan use
use ApaKabar;
}
$obj = new Pesan();
echo $obj->apaKabar();
3. Multiple trait
Satu class boleh memakai lebih dari satu trait, cara memanggilnya dipisahkan oleh koma
trait ApaKabar
{
public function apaKabar() {
return "Apa kabar?" . PHP_EOL;
}
}
trait SelamatPagi
{
public function selamatPagi() {
return "Selamat pagi?";
}
}
class Pesan
{
// menggunakan trait lebih dari satu
use ApaKabar, SelamatPagi;
}
$obj = new Pesan();
echo $obj->apaKabar();
echo $obj->selamatPagi();
4. Sebuah trait tersusun dari banyak trait
Sebuah trait boleh tersusun dari trait yang telah ada
// trait pertama
trait ApaKabar
{
public function apaKabar() {
// PHP_EOL adalah
// garis baru (enter) lintas platform
return "Apa kabar?" . PHP_EOL;
}
}
// trait kedua
trait SelamatPagi
{
public function selamatPagi() {
return "Selamat pagi?";
}
}
// trait ketiga,
trait KabarSelamat
{
// tersusun dari kedua trait di atas
use ApaKabar, SelamatPagi;
}
class Pesan
{
// memakai trait yang
// tersusun dari trait
use KabarSelamat;
}
$obj = new Pesan();
echo $obj->apaKabar();
echo $obj->selamatPagi();
5. Trait tidak bisa dijadikan object (diinstansiasi)
Jika ini tetap dijalankan maka akan keluar error: PHP Fatal error: Uncaught Error: Cannot instantiate trait ApaKabar ...
trait ApaKabar
{
public function apaKabar() {
return "Apa kabar?" . PHP_EOL;
}
}
$obj = new ApaKabar();
6. Urutan prioritas method
Urutan prioritas method dalam trait memiliki dua aturan:
- Method turunan akan ditimpa oleh method yang berasal dari trait
- Current class method akan menimpa method yang berasal dari trait
Ini contoh untuk aturan pertama
class ApaKabar
{
// ini akan diturunkan
public function apaKabar() {
return "Apa kabar?" . PHP_EOL;
}
}
trait SelamatPagi
{
public function selamatPagi() {
return "Selamat pagi?";
}
// apaKabar() dari trait
public function apaKabar() {
return "Apa kabar pagi ini?" . PHP_EOL;
}
}
class Pesan extends ApaKabar
{
use SelamatPagi;
}
$pesan = new Pesan();
// yang dipakai adalah apaKabar() dari trait
echo $pesan->apaKabar();
// jika dijalankan akan keluar
// Apa kabar pagi ini?
Class Pesan
adalah turunan dari class ApaKabar
yaitu dengan meng-extends ApaKabar
dan class Pesan
juga menggunakan trait SelamatPagi
yaitu dengan use SelamatPagi
.
Baik class ApaKabar
maupun trait SelamatPagi
sama-sama memiliki method apaKabar()
tetapi isinya berbeda, yaitu Apa kabar?
dan Apa kabar pagi ini?
.
Dengan kondisi seperti ini ketika object $pesan
memanggil method apaKabar()
maka apaKabar()
yang didahulukan adalah apaKabar()
dalam trait yang berisi Apa kabar pagi ini?
Ini contoh untuk aturan kedua:
trait ApaKabar
{
// apaKabar() dari trait
public function apaKabar() {
return "Apa kabar?";
}
}
class Pesan
{
use ApaKabar;
// apaKabar() dari current class
public function apaKabar() {
return "Apa kabarnya sekarang?";
}
}
$pesan = new Pesan();
// yang dipakai adalah apaKabar() dari class Pesan
// bukan apaKabar() dari trait ApaKabar
echo $pesan->apaKabar();
// coba jalankan maka akan keluar
// Apa kabarnya sekarang?
7. Menangani konflik
Ketika sebuah class menggunakan trait lebih dari satu, kita bisa saja menemukan kondisi dimana trait yang berbeda menggunakan nama method yang sama, seperti contoh ini
trait Selamat
{
public function salam() {
return "Selamat pagi?";
}
}
trait Sapaan
{
public function salam() {
return "Assalamu'alaikum?";
}
}
class Pesan
{
use Selamat, Sapaan;
}
$pesan = new Pesan();
echo $pesan->salam();
Ketika kode program di atas tetap dijalankan maka akan keluar fatal error. Lalu bagaimana agar tetap bisa dijalankan?
Terdapat dua cara:
-
Menyingkirkan method yang tidak dibutuhkan diantara method-method yang sama menggunakan mengggunakan keyword
insteadof
. -
Tetap membawa method yang sama ke dalam class dengan diberikan alias untuk membedakannya yaitu menggunakan keyword
as
Contoh untuk cara pertama:
trait Ucapan
{
public function salam() {
return "Pagi....?";
}
}
trait Selamat
{
public function salam() {
return "Assalamu'alaikum?";
}
}
trait Sapaan
{
public function salam() {
return "Selamat pagi?";
}
}
class Pesan
{
// mengeliminasi method salam()
// dari trait Ucapan dan Sapaan
// mengguanakan insteadof
use Ucapan, Selamat, Sapaan {
Selamat::salam insteadof Ucapan, Sapaan;
}
}
$pesan = new Pesan();
echo $pesan->salam();
jika kita perhatikan kode program di atas dalam class Pesan
terdapat Selamat::salam insteadof Ucapan, Sapaan;
yang artinya yang akan digunakan adalah method salam()
dalam trait Selamat
bukan dari trait Ucapan
dan Sapaan
.
Contoh untuk cara kedua:
trait Ucapan
{
public function salam() {
return "Pagi....?";
}
}
trait Selamat
{
public function salam() {
return "Assalamu'alaikum?" . PHP_EOL;
}
}
trait Sapaan
{
public function salam() {
return "Selamat pagi?";
}
}
class Pesan
{
// membuat alias menggunakan as
// krn ingin tetap memakai salam()
// dari trait Sapaan
use Ucapan, Selamat, Sapaan {
Selamat::salam insteadof Ucapan, Sapaan;
Sapaan::salam as salamKedua;
}
}
$pesan = new Pesan();
echo $pesan->salam();
echo $pesan->salamKedua();
jika kita perhatikan kode program di atas dalam class Pesan
terdapat Sapaan::salam as salamKedua;
artinya method salam()
dalam trait Sapaan
tetap dipakai tetapi diberikan alias salamKedua
agar beda dengan salam()
dari trait Selamat
.
8. Trait boleh memiliki property
Trait boleh memiliki property tetapi class yang menggunakan trait tersebut tidak diizinkan mendefinisikan kembali property dengan nama yang sama.
Jika class tetap mendefinisikan ulang property dengan nama yang sama, selama tingkat visibilitas dan value-nya sama dengan property yang berada dalam trait maka akan keluar peringatan E_STRICT
.
Jika tingkat visibilitas dan atau value-nya tidak sama dengan property yang berada dalam trait maka akan keluar fatal error.
trait Selamat {
public $satu = 1;
protected $dua = 2;
}
class Pesan {
use Selamat;
public $satu = 1; // keluar peringatan
public $dua = 2; // Fatal error
}
9. Method dalam trait boleh mengakses method dan property dalam class yang memakainya meskipun private
trait BukaPesan
{
protected function BukaPesan() {
return $this->pesan;
}
}
class PesanPrivate
{
use BukaPesan;
private $pesan = 'Ini pesan private';
public function pesanPrivate() {
return $this->BukaPesan();
}
}
$pesan = new PesanPrivate();
echo $pesan->pesanPrivate();
// bisa akses pesan private, coba praktekkan
10. Trait boleh memiliki abstract method
Penggunaannya sama saja seperti dalam abstrct class
trait Selamat{
public function salam() {
echo 'Selamat pagi '. $this->getName();
}
abstract public function getName();
}
class Pesan {
private $name;
use Selamat;
public function getName() {
return $this->name;
}
public function setName($name) {
$this->name = $name;
}
}
$obj = new Pesan();
$obj->setName('Andi');
echo $obj->salam(); // Selamat pagi Andi
11. Merubah visibility method
Method dalam trait boleh diubah visibility-nya oleh class menggunakan keyword as
trait Selamat {
public function malam() {
echo 'Selamat malam!';
}
}
// merubah visibility malam()
class Pesan {
use Selamat { malam as protected; }
}
// malam() dibuat alias menjadi ucapanPrivate()
// dan diubah visibility ke private
// sementara malam() visibility-nya tidak berubah
class PesanKedua {
use Selamat { malam as private ucapanPrivate; }
}
Banyak banget ya tulisannya? 😛 walaupun banyak tapi mudah difahami kan? 😊