Saya mengkode dengan pola keadaan untuk perangkat tertanam. Saya memiliki kelas dasar / abstrak yang disebut State dan kemudian setiap kelas state diskrit (konkret) mengimplementasikan Kelas State abstrak.
Di Kelas Negara saya memiliki beberapa Metode Abstrak. Jika saya tidak menerapkan metode abstrak di kelas diskrit (beton), Visual Studio akan memberikan kesalahan seperti ini:
... Kesalahan 1 'myConcreteState' tidak menerapkan anggota abstrak bawaan 'myAbstractState'
Sekarang: Saya mencoba membuat properti String untuk setiap State yang disebut StateName. Setiap kali saya membuat kelas konkret baru, saya perlu mendefinisikan StateName. Saya ingin VS melempar kesalahan jika saya tidak menggunakannya. Apakah ada cara sederhana untuk melakukan hal ini?
Saya sudah mencoba ini di kelas abstrak / dasar:
public abstract string StateName { get; set; }
Tetapi saya tidak perlu menerapkan metode Get and Set di setiap Negara.
Pertanyaan yang Direvisi: Dalam situasi yang ideal, setiap Kelas Negara akan diharuskan untuk memiliki StateName yang didefinisikan dan diwarisi dari kelas dasar yang abstrak.
StateName = "MyState1"; //or whatever the state's name is
Jika pernyataan itu hilang maka Visual Studio akan menghasilkan kesalahan seperti yang dijelaskan di atas. Apakah ini mungkin dan jika iya, bagaimana?
Jawaban:
Saya kira cara "benar" untuk melakukan ini adalah memiliki konstruktor yang dilindungi pada kelas dasar yang memerlukan nama negara sebagai parameter.
Negara konkret kemudian menyediakan konstruktor publik yang secara implisit memanggil konstruktor kelas dasar dengan nama yang sesuai.
Karena kelas dasar tidak mengekspos konstruktor lain (baik yang dilindungi maupun publik), masing-masing kelas yang diwariskan harus melalui konstruktor tunggal ini dan karenanya perlu mendefinisikan nama.
Perhatikan bahwa Anda tidak perlu memberikan nama ketika Anda membuat keadaan konkret karena konstruktornya yang menangani itu:
sumber
...:base(arg1, arg2)
! Ini adalah solusi yang saya cari. Ini benar-benar membantu menjaga kode negara saya lebih konsisten.Pada C # 6 (saya percaya - C #: Baru dan Peningkatan C # 6.0 ) Anda dapat membuat properti pengambil saja. Jadi Anda bisa mendeklarasikan kelas dasar Anda seperti itu -
Dan kemudian di sub-kelas Anda, Anda dapat menerapkan
State
seperti -Atau bahkan lebih rapi menggunakan operator lambda -
Keduanya akan selalu mengembalikan "State_1" dan tidak berubah.
sumber
public override string name { get; } = "State_1";
yang kemudian tidak perlu mengevaluasi kembali nilainya setiap kali.Persyaratan Anda merupakan kontradiksi:
vs.
Tidak ada fitur bahasa yang memungkinkan Anda untuk memaksa keberadaan anggota hanya dalam beberapa sub kelas. Lagi pula, tujuan menggunakan kelas super adalah mengandalkan fakta bahwa semua subclass akan memiliki semua anggota kelas super (dan mungkin lebih). Jika Anda ingin membuat kelas yang bertindak sebagai
State
tetapi tidak memiliki nama, maka menurut definisi, mereka seharusnya (/ tidak bisa) tidak menjadi subkelas dariState
.Anda harus mengubah persyaratan Anda atau menggunakan sesuatu selain warisan sederhana.
Solusi yang mungkin dengan kode seperti itu adalah membuat metode secara
State
abstrak dan mengembalikan string kosong.sumber
StateName = "MyState1"
di setiap Negara. Jika saya tidak memiliki pernyataan di kelas negara, maka idealnya Visual Studio akan menghasilkan kesalahan.return "MyState1"
sebagai implementasinya, dan dapat menambahkan penyimpanan yang dapat berubah untuk nilai jika mereka membutuhkannya. Tetapi Anda perlu mengklarifikasi persyaratan dalam pertanyaan - apakah setiap jenis negara memerlukan StateName yang dapat dibaca, dan apakah semua jenis negara mengharuskannya untuk dimutasi setelah penciptaan?