I've telah bekerja dengan penyedia a fair bit akhir-akhir ini, dan saya datang di sebuah situasi yang menarik di mana saya ingin memiliki sebuah kelas abstrak yang abstrak metode statis. Saya baca beberapa tulisan tentang topik tersebut, dan sepertinya masuk akal, tetapi ada penjelasan yang jelas?
Metode statis tidak contoh dengan demikian, mereka're hanya tersedia tanpa objek referensi.
Panggilan untuk metode statis dilakukan melalui nama kelas, tidak melalui objek referensi, dan Intermediate Language (IL) kode untuk panggilan ini akan memanggil metode abstrak melalui nama class yang didefinisikan itu, belum tentu nama kelas anda digunakan.
Mari saya beri contoh.
Dengan kode berikut:
public class A
{
public static void Test()
{
}
}
public class B : A
{
}
Jika anda menelepon B. Tes, seperti ini:
class Program
{
static void Main(string[] args)
{
B.Test();
}
}
Maka kode yang sebenarnya dalam metode Utama adalah sebagai berikut:
.entrypoint
.maxstack 8
L0000: nop
L0001: call void ConsoleApplication1.A::Test()
L0006: nop
L0007: ret
Seperti yang anda lihat, panggilan akan dibuat untuk A. Tes, karena itu adalah kelas yang didefinisikan, dan tidak B. Tes, meskipun anda dapat menulis kode dengan cara itu.
Jika anda memiliki jenis kelas, seperti di Delphi, di mana anda dapat membuat sebuah variabel yang mengacu pada jenis dan bukan objek, anda akan memiliki lebih banyak digunakan untuk virtual dan dengan demikian abstrak metode statis (dan juga konstruktor), tetapi mereka tidak't yang tersedia dan dengan demikian statis panggilan non-virtual dalam .NET.
Saya menyadari bahwa IL desainer dapat memungkinkan kode yang akan disusun untuk memanggil B. Tes, dan menyelesaikan panggilan pada saat runtime, tapi itu masih tidak't menjadi virtual, anda masih akan memiliki untuk menulis beberapa jenis nama kelas yang ada.
Metode Virtual, dan dengan demikian yang abstrak, yang hanya berguna ketika anda're menggunakan variabel yang, pada saat runtime, yang dapat mengandung berbagai jenis benda-benda, dan dengan demikian anda ingin memanggil metode yang tepat untuk saat ini objek yang anda miliki dalam variabel. Dengan metode statis, anda perlu untuk pergi melalui nama kelas, jadi metode yang tepat untuk memanggil diketahui pada waktu kompilasi karena dapat't dan tidak't perubahan.
Dengan demikian, maya/abstrak metode statis tidak tersedia di .NET.
Metode statis tidak dapat diwariskan atau diganti, dan itulah mengapa mereka dapat't menjadi abstrak. Sejak statis metode yang didefinisikan pada jenis, bukan contoh, kelas, mereka harus disebut secara eksplisit pada jenis itu. Jadi, ketika anda ingin memanggil metode pada kelas anak, anda perlu menggunakan namanya untuk menyebutnya. Hal ini membuat warisan yang tidak relevan.
Asumsikan anda bisa, untuk saat ini, mewarisi metode statis. Bayangkan skenario ini:
public static class Base
{
public static virtual int GetNumber() { return 5; }
}
public static class Child1 : Base
{
public static override int GetNumber() { return 1; }
}
public static class Child2 : Base
{
public static override int GetNumber() { return 2; }
}
Jika anda panggilan dan Pilihan.GetNumber(), metode mana yang akan dipanggil? Nilai yang dikembalikan? Cukup mudah untuk melihat bahwa tanpa membuat contoh dari benda-benda, warisan agak keras. Abstrak metode tanpa warisan hanyalah metode yang don't memiliki tubuh, sehingga dapat't akan dipanggil.
Responden yang lain (McDowell) mengatakan bahwa polimorfisme hanya bekerja untuk contoh-contoh objek. Yang harus memenuhi syarat; ada bahasa yang mengobati kelas sebagai contoh "Kelas" atau "Metaclass" type. Bahasa-bahasa ini mendukung polimorfisme untuk kedua contoh dan kelas (statis) metode.
C#, seperti Java dan C++ sebelum itu, tidak seperti bahasa; statis
kata kunci yang digunakan secara eksplisit untuk menunjukkan bahwa metode statis-terikat daripada dinamis/virtual.
Berikut ini adalah situasi di mana pasti ada kebutuhan untuk warisan bagi statis bidang dan metode:
abstract class Animal
{
protected static string[] legs;
static Animal() {
legs=new string[0];
}
public static void printLegs()
{
foreach (string leg in legs) {
print(leg);
}
}
}
class Human: Animal
{
static Human() {
legs=new string[] {"left leg", "right leg"};
}
}
class Dog: Animal
{
static Dog() {
legs=new string[] {"left foreleg", "right foreleg", "left hindleg", "right hindleg"};
}
}
public static void main() {
Dog.printLegs();
Human.printLegs();
}
//what is the output?
//does each subclass get its own copy of the array "legs"?
Kami benar-benar menimpa metode statis (di delphi), it's sedikit jelek, tapi itu bekerja dengan baik untuk kebutuhan kita.
Kita menggunakannya sehingga kelas dapat memiliki daftar benda-benda yang tersedia tanpa kelas contoh, misalnya, kita memiliki metode yang terlihat seperti ini:
class function AvailableObjects: string; override;
begin
Result := 'Object1, Object2';
end;
It's jelek tapi diperlukan, dengan cara ini kita dapat instantiate hanya apa yang dibutuhkan, alih-alih memiliki semua kelas instantianted hanya untuk mencari benda-benda yang tersedia.
Ini adalah sebuah contoh yang sederhana, tapi aplikasi itu sendiri adalah aplikasi client-server yang memiliki semua kelas yang tersedia hanya dalam satu server, dan beberapa klien yang berbeda yang mungkin tidak perlu semua server memiliki dan tidak akan pernah perlu contoh objek.
Jadi, ini adalah jauh lebih mudah untuk mempertahankan daripada memiliki satu server yang berbeda aplikasi untuk masing-masing klien.
Harapan contoh yang jelas.
Abstrak metode yang secara implisit virtual. Abstrak metode ini membutuhkan sebuah contoh, namun metode statis tidak memiliki contoh. Jadi, anda dapat memiliki sebuah metode statis dalam sebuah kelas abstrak, itu tidak statis abstrak (atau abstrak statis).