Kontrak IPembayaran pada bab sebelumnya baru berupa janji; janji itu baru berarti ketika ada class yang mengisinya. Transfer bank dan kartu kredit bekerja dengan cara yang berbeda, tetapi keduanya harus mampu memproses pembayaran. Bab ini membahas cara class menyatakan penepatan kontrak dan cara pemanggil memakai hasilnya.
Mengisi Member Kontrak pada Class #
Class menyatakan penepatan kontrak dengan tanda titik dua setelah nama class, lalu mengisi seluruh member interface:
public class KartuKredit : IPembayaran
{
public int BiayaAdmin => 2000;
public void ProsesPembayaran(int jumlah)
{
Console.WriteLine($"Kartu kredit: pembayaran Rp{jumlah} diproses (biaya admin Rp{BiayaAdmin}).");
}
}
public class TransferBank : IPembayaran
{
public int BiayaAdmin => 0;
public void ProsesPembayaran(int jumlah)
{
Console.WriteLine($"Transfer bank: pembayaran Rp{jumlah} diproses (biaya admin Rp{BiayaAdmin}).");
}
}Kedua class menulis public secara eksplisit pada implementasi karena member interface yang diisi wajib dapat diakses pemanggil. Isi implementasi bebas berbeda; yang wajib sama hanya nama member, parameter, dan tipe kembalian sesuai kontrak.
Compiler memeriksa penepatan kontrak saat program dikompilasi, bukan saat program berjalan. Bila satu class menyatakan : IPembayaran tetapi tidak mengisi member kontrak, programmer langsung menerima galat sebelum aplikasi dijalankan. Pemeriksaan dini inilah yang menjaga janji interface tetap tertunaikan.
error CS0535: 'KartuKredit' does not implement interface member 'IPembayaran.ProsesPembayaran(int)'Memakai Implementasi lewat Tipe Interface #
Pemanggil dapat menyimpan object dari class mana pun yang menepati kontrak ke dalam koleksi bertipe interface:
List<IPembayaran> metodeTersedia = new List<IPembayaran>
{
new KartuKredit(),
new TransferBank()
};
foreach (IPembayaran metode in metodeTersedia)
{
metode.ProsesPembayaran(150000);
}Output yang Dihasilkan:
Kartu kredit: pembayaran Rp150000 diproses (biaya admin Rp2000).
Transfer bank: pembayaran Rp150000 diproses (biaya admin Rp0).Mari kita bedah baris demi baris:
List<IPembayaran>— koleksi bertipe interface menampung object dari class mana pun yang menepati kontrak tersebut.new KartuKredit()dannew TransferBank()— kedua object masuk daftar tanpa cast karena keduanya menepatiIPembayaran.foreach (IPembayaran metode in ...)— variabel iterasi bertipe interface, sehingga compiler hanya mengizinkan pemanggilan member kontrak.metode.ProsesPembayaran(150000)— compiler membaca janji dariIPembayaran; runtime menjalankan versi milik object yang sedang ditunjuk.BiayaAdminpada kedua class — property yang sama dijanjikan kontrak diisi nilai berbeda; interface mengatur bentuk member, bukan nilai isinya.
Perilaku pada poin terakhir sama seperti polymorphism pada method overriding: satu pemanggilan, banyak versi pelaksana. Implementasi lewat tipe interface juga membuat penambahan class baru tidak mengubah kode pemanggil; class baru cukup didaftarkan sebagai elemen daftar.