Temel Sınıfta Programcıyı Tanımlamaya Zorlamak İçin Soyut Özellik


10

Gömülü bir cihaz için durum modeliyle kod yazıyorum. Devlet adında bir temel / soyut sınıfım var ve sonra her ayrık (somut) devlet sınıfı soyut Devlet Sınıfını uygular.

Devlet Sınıfında birkaç Soyut Metot var. Ayrık (somut) sınıfta soyut yöntemleri uygulamazsanız, Visual Studio böyle bir hata verir:

... Hata 1 'myConcreteState' devralınan soyut üye 'myAbstractState' uygulamıyor

Şimdi: StateName adlı her durum için bir String özelliği oluşturmaya çalışıyorum. Ne zaman yeni bir somut sınıf oluştursam, StateName tanımlamam gerekir. VS kullanmazsam bir hata atmasını istiyorum. Bunu yapmanın kolay bir yolu var mı?

Ben soyut / temel sınıfta denedim:

public abstract string StateName { get; set; }

Ancak, her bir Devlette Get and Set yöntemlerini uygulamama gerek yok.

Gözden Geçirilmiş Soru: İdeal bir durumda, her Devlet Sınıfının StateName'i tanımlaması ve soyut temel sınıftan miras alması gerekir.

StateName = "MyState1"; //or whatever the state's name is

Bu ifade eksikse, Visual Studio yukarıda açıklandığı gibi bir hata oluşturur. Bu mümkün mü ve eğer mümkünse nasıl?


2
Soruyu anlamıyorum.
Ben Aaronson

Bunu yapmak için "doğru" yolu devlet sınıfı bir parametre olarak gerektiren temel sınıf üzerinde korumalı bir kurucu var sanırım.
Roman Reiner

@RomenReiner Ben de bunu düşündüm .. ama gereksiz görünüyor çünkü her zaman bir durum değiştirmek / çağırmak, adı yazmak zorunda kalacak.
GisMofx

@BenAaronson Soruyu dibe yakın açıkladım.
GisMofx

Durum adı tür başına sabit mi yoksa örnek başına sabit mi?
Roman Reiner

Yanıtlar:


16

Bunu yapmak için "doğru" yolu devlet sınıfı bir parametre olarak gerektiren temel sınıf üzerinde korumalı bir kurucu var sanırım.

public abstract class State
{
    private readonly string _name;

    protected State(string name)
    {
        if(String.IsNullOrEmpty(name))
            throw new ArgumentException("Must not be empty", "name");

        _name = name;
    }

    public string Name { get { return _name; } }
}

Daha sonra somut devletler, temel sınıf yapıcısını örtük olarak uygun adla çağıran bir kamu kurucu sağlar.

public abstract class SomeState : State
{
    public SomeState() : base("The name of this state")
    {
        // ...
    }
}

Temel sınıf başka herhangi bir kurucu (ne korumalı ne de kamu) açığa vurmadığından, miras alan her sınıfın bu tek kurucudan geçmesi gerekir ve bu nedenle bir ad tanımlaması gerekir.

Somut bir durumu başlatırken adı vermeniz gerekmediğini unutmayın, çünkü kurucusu bununla ilgilenir:

var someState = new SomeState(); // No need to define the name here
var name = someState.Name; // returns "The name of this state"

1
Teşekkürler! Gerçekte, temel sınıf kurucum artık ek bir argüman alıyor; iki girişim var. Bunu kurar kurmaz, devlet sınıfı kurucularında ek bir tartışmaya ihtiyacım olduğu hataları alıyorum ...:base(arg1, arg2)! Bu aradığım bir çözüm. Bu, Devlet kodumu daha tutarlı tutmamda gerçekten yardımcı oluyor.
GisMofx

3

C # 6 (Sanırım - C #: Yeni ve Geliştirilmiş C # 6.0 ) itibariyle yalnızca alıcı özellikleri oluşturabilirsiniz. Böylece temel sınıfınızı şöyle ilan edebilirsiniz -

public abstract class State
{
    public abstract string name { get; }

    // Your other functions....
}

Ve sonra alt sınıfınızda böyle uygulayabilirsiniz State-

public class SomeState : State
{
    public override string name { get { return "State_1"; } }
}

Veya lambda operatörünü kullanarak daha da temiz -

public class SomeState : State
{
    public override string name => "State_1";
}

Her ikisi de her zaman "State_1" döndürür ve değişmez olur.


1
bu public override string name { get; } = "State_1";her seferinde değerin yeniden değerlendirilmesi gerekmeyecek şekilde yazılabilir .
Dave Cousineau

2

Gereksinimleriniz bir çelişki:

StateName adlı her durum için bir dize özelliği oluşturmaya çalışıyorum .

vs.

Fakat bunların hepsini her bir Devlette uygulamaya gerek yok .

Sadece birkaç alt sınıfta bir üyenin varlığını zorlamanızı sağlayan bir dil özelliği yoktur. Sonuçta, bir süper sınıf kullanmanın amacı, tüm alt sınıfların süper sınıfın tüm üyelerine (ve muhtemelen daha fazlasına) sahip olacağına güvenmektir. Eğer bir gibi davranan Stateama bir adı olmayan sınıflar oluşturmak istiyorsanız , tanım gereği, alt sınıfları olmamalıdır (/ can) State.

Gereksinimlerinizi değiştirmeniz veya basit miras dışında bir şey kullanmanız gerekir.

Kodu olduğu gibi olası bir çözüm, yöntemi Statesoyut olmayan bir şekilde yapmak ve boş bir dize döndürmek olabilir.


Sanırım bu ikinci ifadeyi bağlamdan çıkardınız, ama açıklığa kavuşacağım. Get / Set yöntemlerine ihtiyacım yok, sadece StateName = "MyState1"her eyalette istiyorum . State sınıfta bu deyim yoksa, ideal olarak Visual Studio bir hata oluşturur.
GisMofx

3
@GisMofx Her alt sınıftaki durum adını zorlamak istiyorsanız, özetini alın, ancak bir durum gerektirmez. Daha sonra her alt sınıfın return "MyState1"kendi uygulamaları olarak sağlanması gerekir ve ihtiyaç duymaları halinde değer için değiştirilebilir depolama alanı ekleyebilir. Ancak sorudaki gereklilikleri açıklığa kavuşturmanız gerekiyor - her durum türü okunabilen bir DurumAdı gerektiriyor mu ve her tür durum yaratıldıktan sonra mutasyona uğratılmasını gerektiriyor mu?
Pete Kirkham

@PeteKirkham her eyalet bir isim gerektirir, yaratıldıktan sonra mutasyona uğratılmamalıdır. Eyaletlerin isimleri statik / değişmezdir.
GisMofx
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.