Saya mengevaluasi CMS open source yang disebut Piranha ( http://piranhacms.org/ ) untuk digunakan dalam salah satu proyek saya. Saya menemukan kode berikut ini menarik dan agak membingungkan, setidaknya bagi saya. Dapatkah beberapa orang membantu saya memahami mengapa kelas mewarisi dari jenis yang sama?
public abstract class BasePage<T> : Page<T> where T : BasePage<T>
{
/// <summary>
/// Gets/sets the page heading.
/// </summary>
[Region(SortOrder = 0)]
public Regions.PageHeading Heading { get; set; }
}
Jika kelas BasePage<T>
sedang didefinisikan, mengapa mewarisi dari Page<T> where T: BasePage<T>
? Apa tujuan spesifik yang dilayaninya?
c#
architecture
.net
cms
Xami Yen
sumber
sumber
Jawaban:
Bukan, ini merupakan turunan dari
Page<T>
, tetapiT
itu sendiri dibatasi untuk menjadi parameter oleh tipe yang diturunkanBasePage<T>
.Untuk menyimpulkan mengapa, Anda harus melihat bagaimana parameter tipe
T
sebenarnya digunakan. Setelah beberapa penggalian, saat Anda naik ke rantai warisan, Anda akan menemukan kelas ini:( github )
Sejauh yang saya bisa lihat, satu-satunya tujuan untuk batasan generik adalah untuk memastikan bahwa
Create
metode mengembalikan tipe abstrak paling tidak mungkin.Tidak yakin apakah itu sepadan, tapi mungkin ada beberapa alasan bagus di baliknya, atau bisa saja untuk kenyamanan, atau mungkin tidak ada terlalu banyak zat di baliknya dan itu hanya cara yang terlalu rumit untuk menghindari gips (BTW, saya Saya tidak menyiratkan bahwa inilah yang terjadi di sini, saya hanya mengatakan bahwa kadang-kadang orang melakukan itu).
Perhatikan bahwa ini tidak memungkinkan mereka untuk menghindari refleksi - yang
api.Pages
adalah gudang halaman yang memperolehtypeof(T).Name
, dan dibagikan sebagaitypeId
kecontentService.Create
metode ( lihat di sini ).sumber
Salah satu penggunaan umum ini terkait dengan konsep tipe diri: parameter tipe yang memutuskan untuk tipe saat ini. Katakanlah Anda ingin mendefinisikan antarmuka dengan
clone()
metode. Theclone()
Metode harus selalu mengembalikan sebuah instance dari kelas yang itu disebut. Bagaimana Anda mendeklarasikan metode itu? Dalam sistem generik yang memiliki tipe mandiri, mudah. Anda hanya mengatakan itu kembaliself
. Jadi jika saya memiliki kelasFoo
, metode klon harus dinyatakan untuk kembaliFoo
. Di Jawa dan (dari pencarian sepintas) C #, ini bukan pilihan. Anda malah melihat deklarasi seperti apa yang Anda lihat di kelas ini. Penting untuk dipahami bahwa ini bukan hal yang sama dengan tipe diri dan batasan yang diberikannya lebih lemah. Jika Anda memilikiFoo
danBar
kelas yang keduanya berasalBasePage
, Anda dapat (jika saya tidak salah) mendefinisikan Foo untuk menjadi parameter olehBar
. Itu mungkin berguna tapi saya pikir biasanya, sebagian besar waktu, ini akan digunakan seperti tipe diri dan itu hanya dipahami bahwa meskipun Anda dapat berkeliling dan mengganti dengan tipe lain, itu bukan sesuatu yang harus Anda lakukan. Saya bermain-main dengan ide ini sejak lama tetapi sampai pada kesimpulan bahwa itu tidak sepadan dengan usaha karena keterbatasan generik Java. C # generics tentu saja lebih lengkap tetapi tampaknya memiliki batasan yang sama.Lain waktu pendekatan ini digunakan adalah ketika Anda sedang membangun tipe seperti grafik seperti pohon atau struktur rekursif lainnya. Deklarasi memungkinkan jenis untuk memenuhi persyaratan Halaman tetapi lebih lanjut jenis. Anda mungkin melihat ini di struktur pohon. Sebagai contoh,
Node
mungkin parameter denganNode
memungkinkan untuk implementasi untuk menentukan bahwa mereka bukan hanya Pohon yang mengandung jenis Node tetapi sub-jenis Node tertentu (biasanya tipe mereka sendiri.) Saya pikir itu lebih dari apa yang terjadi di sini.sumber
Menjadi orang yang benar-benar menulis kode saya dapat mengkonfirmasi bahwa Filip benar dan generik referensi diri sebenarnya kenyamanan untuk menyediakan metode Buat diketik pada kelas dasar.
Seperti yang dia sebutkan, masih ada banyak refleksi yang terjadi, dan pada akhirnya hanya nama tipe yang digunakan untuk menyelesaikan tipe halaman. Alasan untuk ini adalah bahwa Anda dapat memuat model dinamis juga, yaitu mewujudkan model tanpa memiliki akses ke tipe CLR yang membuatnya di tempat pertama.
sumber