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
Method1
dan menimpaMethod2
harus mengulangi validasi argumen. - dalam hal pengembang kelas dasar memutuskan untuk menambahkan sesuatu di sekitar bagian yang dapat dikustomisasi
Method1
atau yangMethod2
lebih 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 ProtectedAbstractOrVirtual
kelas 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 Stream
kelas untuk memverifikasi ini.
Apa pendapat Anda tentang pedoman itu? Apakah itu masuk akal, atau Anda pikir itu terlalu rumit API?
protected
ini 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.
virtual
memungkinkan penggantian opsional. Metode Anda mungkin harus bersifat publik, karena mungkin tidak diganti. Membuat metodeabstract
memaksa Anda untuk menimpanya; mereka seharusnyaprotected
, karena mereka tidak terlalu berguna dalam suatupublic
konteks.