Class Sealed
Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan C# di Coddy. Pelajaran 22 dari 70.
Terkadang kamu ingin menghentikan rantai pewarisan. Kata kunci sealed mencegah sebuah class diwariskan, sehingga implementasinya terkunci dan tidak ada class lain yang dapat memperluasnya.
public sealed class FinalDog : Animal
{
public override void Speak()
{
Console.WriteLine("Woof!");
}
}
// Ini akan menyebabkan error saat compile:
// public class SuperDog : FinalDog { }Mengapa kamu perlu menyegel class? Keamanan dan integritas desain adalah alasan umum. Jika kamu telah merancang class dengan cermat dan tidak ingin siapa pun mengubah perilakunya melalui pewarisan, menyegelnya memastikan implementasimu tetap utuh.
Kamu juga dapat menyegel method satu per satu, bukan seluruh class. Ini mencegah penimpaan lebih lanjut sambil tetap memungkinkan class itu sendiri diwarisi:
public class Dog : Animal
{
public sealed override void Speak()
{
Console.WriteLine("Woof!");
}
}
public class Puppy : Dog
{
// Tidak bisa override Speak() karena sudah sealed
// Namun, kamu bisa menambahkan method baru
public void Whimper()
{
Console.WriteLine("Whimper...");
}
}Perhatikan bahwa sealed pada method harus digabungkan dengan override. Kamu hanya bisa menyegel method yang sudah virtual di class induk. Ini memberimu kendali yang tepat: izinkan beberapa penyesuaian dalam hierarki pewarisan, lalu kunci pada titik tertentu.
Tantangan
MudahMari kita bangun sistem pemrosesan pembayaran yang menunjukkan cara menggunakan sealed untuk mengunci implementasi penting. Kamu akan membuat hierarki tempat beberapa metode pembayaran dapat diperluas, tetapi metode yang paling aman diberi sealed untuk mencegah perubahan.
Kamu akan membuat empat file untuk mengatur kodemu:
PaymentMethod.cs: Definisikan classPaymentMethoddalam namespacePayments. Base class ini memiliki propertyName(string) dan constructor yang menetapkannya. Sertakan methodvirtualbernamaProcessPayment(decimal amount)yang mengembalikan"Processing ${amount} via {Name}".CreditCardPayment.cs: Definisikan classCreditCardPaymentdalam namespacePaymentsyang mewarisiPaymentMethod. Tambahkan propertyCardNumber(string). Constructor menerima nama dan nomor kartu, lalu menggunakanbaseuntuk meneruskan nama. OverrideProcessPaymentdengan kata kuncisealedagar class turunan berikutnya tidak dapat mengubah perilaku ini. Method ini harus mengembalikan"Charging ${amount} to card ending in {last 4 digits of CardNumber}".BankTransfer.cs: Definisikan classBankTransferdengan kata kuncisealeddalam namespacePaymentsyang mewarisiPaymentMethod. Seluruh class ini diberisealed, jadi tidak ada yang dapat mewarisinya. Tambahkan propertyBankName(string). Constructor menerima nama dan nama bank. OverrideProcessPaymentagar mengembalikan"Transferring ${amount} from {BankName}".Program.cs: Di file utama, buat instance dari ketiga tipe pembayaran menggunakan nilai input. Simpan sebagai referensiPaymentMethoddan panggilProcessPaymentpada masing-masing untuk menunjukkan polimorfisme dengan implementasi yang diberisealed.
Kamu akan menerima empat input:
- Nomor kartu kredit (16 digit)
- Nama bank
- Jumlah pembayaran
Cetak hasil pemrosesan pembayaran melalui setiap method:
{base PaymentMethod result}
{CreditCardPayment result}
{BankTransfer result}Misalnya, jika inputnya adalah 1234567890123456, First National, dan 150.00, outputnya harus seperti berikut:
Processing $150.00 via Generic
Charging $150.00 to card ending in 3456
Transferring $150.00 from First NationalGunakan "Generic" sebagai nama untuk instance base PaymentMethod, "Credit Card" untuk pembayaran kartu kredit, dan "Bank Transfer" untuk transfer bank.
Method yang diberi sealed di CreditCardPayment memastikan bahwa jika seseorang membuat subclass, mereka tidak dapat mengubah cara pembayaran kartu kredit diproses. Class BankTransfer yang diberi sealed mencegah semua pewarisan. Keduanya merupakan pola keamanan penting dalam sistem pembayaran!
Coba sendiri
using System;
using Payments;
class Program
{
public static void Main(string[] args)
{
// Baca input
string cardNumber = Console.ReadLine();
string bankName = Console.ReadLine();
decimal amount = Convert.ToDecimal(Console.ReadLine());
// TODO: Buat instance PaymentMethod dasar dengan nama "Generic"
// Simpan sebagai referensi PaymentMethod
// TODO: Buat instance CreditCardPayment dengan nama "Credit Card" dan nomor kartu
// Simpan sebagai referensi PaymentMethod
// TODO: Buat instance BankTransfer dengan nama "Bank Transfer" dan nama bank
// Simpan sebagai referensi PaymentMethod
// TODO: Panggil ProcessPayment pada masing-masing instance dan cetak hasilnya
// Setiap hasil harus berada di baris tersendiri
}
}
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Objek
1Dasar-Dasar OOP
File EksternalNamespace & DirektifPengantar class & objectKata Kunci 'this'Method dan ParameterField vs PropertyKonstruktorInisialisasi objectRingkasan: Kalkulator Sederhana4Pewarisan
Sintaks Dasar Pewarisan (:)Kata Kunci 'base'Kata Kunci Virtual & OverrideClass SealedBase Class 'object'Rangkuman: Hierarki Karyawan7Fitur Lanjutan
Overloading OperatorIndexer (this[])Penimpaan ToString()Extension methodRingkasan: Custom list2Property & Anggota Statis
Property yang Diimplementasikan OtomatisProperty Hanya Baca dan Hanya TulisField dan method StatisClass StatisAnggota Berbentuk Ekspresi5Polimorfisme & Antarmuka
Polimorfisme saat kompilasi vs runtimeAntarmuka vs kelas abstrakBeberapa antarmukaAntarmuka eksplisitUpcasting & DowncastingRingkasan, Kalkulator Bentuk8Konsep OOP Lanjutan
Komposisi daripada PewarisanGenerics (class dan method)Delegate dan EventAtribut dan ReflectionIDisposable dan Pernyataan usingDasar-Dasar Dependency Injection11Pola Desain Bagian 2
Pola PerintahPola AdapterPola DecoratorPola Template MethodPola StatePola CompositeLatihan sendiri: Compiler C# online