Kembali pada tahun 2000-an, seorang kolega saya mengatakan kepada saya bahwa itu adalah anti-pola untuk membuat metode publik virtual atau abstrak.
Misalnya, ia menganggap kelas seperti ini tidak dirancang dengan baik:
public abstract class PublicAbstractOrVirtual
{
public abstract void Method1(string argument);
public virtual void Method2(string argument)
{
if (argument == null) throw new ArgumentNullException(nameof(argument));
// default implementation
}
}
Dia menyatakan itu
- pengembang kelas turunan yang mengimplementasikan
Method1dan menimpaMethod2harus mengulangi validasi argumen. - dalam hal pengembang kelas dasar memutuskan untuk menambahkan sesuatu di sekitar bagian yang dapat dikustomisasi
Method1atau yangMethod2lebih baru, ia tidak dapat melakukannya.
Sebagai gantinya, kolega saya mengusulkan pendekatan ini:
public abstract class ProtectedAbstractOrVirtual
{
public void Method1(string argument)
{
if (argument == null) throw new ArgumentNullException(nameof(argument));
this.Method1Core(argument);
}
public void Method2(string argument)
{
if (argument == null) throw new ArgumentNullException(nameof(argument));
this.Method2Core(argument);
}
protected abstract void Method1Core(string argument);
protected virtual void Method2Core(string argument)
{
// default implementation
}
}
Dia mengatakan kepada saya membuat metode publik (atau properti) virtual atau abstrak sama buruknya dengan membuat bidang publik. Dengan membungkus bidang ke dalam properti, seseorang dapat mencegat akses apa pun ke bidang itu nanti, jika perlu. Hal yang sama berlaku untuk anggota virtual / abstrak publik: membungkus mereka seperti yang ditunjukkan dalam ProtectedAbstractOrVirtualkelas memungkinkan pengembang kelas dasar untuk mencegat panggilan yang masuk ke metode virtual / abstrak.
Tapi saya tidak melihat ini sebagai pedoman desain. Bahkan Microsoft tidak mengikutinya: lihat saja Streamkelas untuk memverifikasi ini.
Apa pendapat Anda tentang pedoman itu? Apakah itu masuk akal, atau Anda pikir itu terlalu rumit API?
protectedini paling berguna ketika Anda ingin mengekspos anggota pribadi dari kelas abstrak ke kelas turunan. Bagaimanapun, saya tidak terlalu peduli dengan pendapat teman Anda; pilih pengubah akses yang paling masuk akal untuk situasi khusus Anda.
virtualmemungkinkan penggantian opsional. Metode Anda mungkin harus bersifat publik, karena mungkin tidak diganti. Membuat metodeabstractmemaksa Anda untuk menimpanya; mereka seharusnyaprotected, karena mereka tidak terlalu berguna dalam suatupublickonteks.