Sudah terkenal bagi mereka yang akrab dengan sejarah bahwa C # dan .NET framework dimulai sebagai dasarnya "Delphi ditulis ulang untuk merasa seperti Java," dirancang oleh kepala pengembang di belakang Delphi, Anders Hejlsberg. Hal-hal telah menyimpang sedikit sejak itu, tetapi sejak awal kemiripannya begitu jelas sehingga bahkan ada beberapa spekulasi serius bahwa .NET sebenarnya awalnya produk Borland.
Tapi saya telah melihat beberapa .NET belakangan ini, dan salah satu fitur yang paling menarik dan berguna dari Delphi tampaknya hilang seluruhnya: konsep kelas sebagai tipe data kelas satu. Bagi mereka yang tidak terbiasa dengan itu, tipe TClass
mewakili referensi ke kelas, mirip dengan Type
tipe .NET. Tapi di mana. NET menggunakan Type
untuk refleksi, Delphi menggunakan TClass
sebagai bagian built-in yang sangat penting dari bahasa. Hal ini memungkinkan untuk berbagai idiom berguna yang tidak dan tidak bisa ada tanpa itu, seperti variabel subtipe kelas dan metode kelas virtual.
Setiap bahasa OO memiliki metode virtual, di mana kelas yang berbeda menerapkan konsep dasar yang sama dari metode dengan cara yang berbeda, dan kemudian metode yang tepat dipanggil pada saat runtime berdasarkan pada jenis objek objek yang dipanggil. Delphi memperluas konsep ini ke kelas: jika Anda memiliki referensi TClass yang didefinisikan sebagai subtipe kelas tertentu ( class of TMyClass
artinya variabel dapat menerima referensi kelas apa pun yang diwarisi dari TMyClass
, tetapi bukan apa pun di luar heirarki) yang memiliki metode virtual ruang lingkup yang melekat pada itu, mereka dapat dipanggil tanpa instance dengan menggunakan tipe kelas yang sebenarnya. Menerapkan pola ini ke konstruktor membuat implementasi pabrik menjadi sepele, misalnya.
Tampaknya tidak ada yang setara di .NET. Dengan referensi kelas yang berguna (dan terutama konstruktor virtual dan metode kelas virtual lainnya!), Adakah yang mengatakan sesuatu tentang mengapa mereka ditinggalkan?
Contoh spesifik
Bentuk Deserialisasi
Delphi VCL menyimpan formulir dalam DFM
format, DSL untuk menggambarkan hierarki komponen. Saat pembaca formulir mem-parsing data DFM, itu berjalan melintasi objek yang digambarkan seperti ini:
object Name: ClassName
property = value
property = value
...
object SubObjectName: ClassName
...
end
end
Yang menarik di sini adalah ClassName
bagiannya. Setiap kelas komponen mendaftarkannya TClass
dengan sistem streaming komponen pada initialization
waktu itu (bayangkan konstruktor statis, hanya sedikit berbeda, dijamin akan terjadi segera pada saat startup.) Ini mendaftarkan setiap kelas dalam sebuah hashmap-class TClass dengan nama kelas sebagai kunci.
Setiap komponen berasal dari TComponent
, yang memiliki konstruktor virtual yang mengambil argumen tunggal Owner: TComponent
,. Setiap komponen dapat menimpa konstruktor ini untuk menyediakan inisialisasi sendiri. Ketika pembaca DFM membaca nama kelas, itu mencari nama dalam hashmap yang disebutkan di atas dan mengambil referensi kelas yang sesuai (atau menimbulkan pengecualian jika tidak ada di sana), kemudian memanggil konstruktor TComponent virtual di atasnya, yang dikenal baik karena fungsi pendaftaran mengambil referensi kelas yang diperlukan untuk turun dari TComponent, dan Anda berakhir dengan objek dengan tipe yang tepat.
Kurangnya ini, setara WinForms adalah ... well ... berantakan besar untuk terus terang, membutuhkan bahasa .NET baru untuk sepenuhnya menerapkan kembali bentuk sendiri (de) serialisasi. Ini agak mengejutkan ketika Anda memikirkannya; karena inti dari memiliki CLR adalah membiarkan banyak bahasa menggunakan infrastruktur dasar yang sama, sistem gaya DFM akan sangat masuk akal.
Kemungkinan diperpanjang
Kelas manajer gambar yang saya tulis dapat diberikan dengan sumber data (seperti jalur ke file gambar Anda) dan kemudian memuat objek gambar baru secara otomatis jika Anda mencoba untuk mengambil nama yang tidak ada dalam koleksi tetapi tersedia di sumber data. Ini memiliki variabel kelas yang diketik sebagai class of
kelas gambar dasar, mewakili kelas dari setiap objek baru yang akan dibuat. Muncul dengan default, tetapi ada beberapa poin, ketika membuat gambar baru dengan tujuan khusus, bahwa gambar harus diatur dengan cara yang berbeda. (Membuatnya tanpa saluran alfa, mengambil metadata khusus dari file PNG untuk menentukan ukuran sprite, dll.)
Ini dapat dilakukan dengan menulis sejumlah besar kode konfigurasi dan mengirimkan opsi khusus ke semua metode yang mungkin berakhir dengan membuat objek baru ... atau Anda bisa membuat subkelas dari kelas gambar dasar yang menimpa metode virtual di mana aspek yang dimaksud akan dikonfigurasikan, dan kemudian menggunakan blok coba / akhirnya untuk sementara mengganti properti "kelas default" yang diperlukan dan kemudian mengembalikannya. Melakukannya dengan variabel referensi kelas jauh lebih sederhana, dan bukan sesuatu yang bisa dilakukan dengan obat generik.
TClass
berguna, dengan beberapa kode sampel? Dalam penelitian internet sepintas saya tentang TClass
, saya menemukan yang TClass
dapat diedarkan sebagai parameter. Ini dilakukan di .NET menggunakan Generics. Metode pabrik ditandai dengan sederhana static
di .NET, dan tidak memerlukan instance kelas untuk mengeksekusi.
TClass
adalah fitur bahasa dasar yang membutuhkan dukungan kompiler. Anda tidak dapat "menulis sendiri" tanpa menulis bahasa Anda sendiri, dan untuk .NET bahkan itu tidak akan cukup karena model objek didefinisikan oleh CLR, bukan oleh bahasa individual. Ini adalah sesuatu yang benar-benar harus menjadi bagian dari .NET framework itu sendiri, atau tidak bisa ada.