C #: полу-абстрактные автоматические свойства? - PullRequest
1 голос
/ 25 апреля 2011

В базовом классе я хочу определить абстрактное получение, но в этот момент мне все равно, какое множество.Как я могу определить сеттер в моем дочернем классе?

Я попробовал несколько вещей, но не могу заставить его работать.Например, я попытался:

public class BaseClass
{
    public abstract bool MyBool { get; }
}

public class ChildClass : BaseClass
{
    public override bool MyBool { get; protected set;}
}

И:

public class BaseClass
{
    public bool MyBool { abstract get; }
}

public class ChildClass : BaseClass
{
    public bool MyBool { override get; protected set;}
}

Я знаю, что могу обойти это, не используя автоматические свойства в дочернем классе и непосредственно устанавливая базовое поле вместо созданиясеттер, но я ищу что-то лучше.

Редактировать : я не хочу добавлять абстрактный сеттер в BaseClass.

Ответы [ 4 ]

4 голосов
/ 25 апреля 2011

Возможно, имеет смысл использовать интерфейс, а не базовый класс. Тогда у вас просто есть классы, которые должны предоставить это свойство для реализации этого интерфейса.

Например, вы можете создать этот интерфейс:

public interface IBoolable {
     bool MyBool { get; }
}

Тогда все еще допустимо реализовать интерфейс следующим образом:

public class BoolableItem : IBoolable {
     public bool MyBool { get; protected set; }
}

Сделано так, что ваш код может безопасно предположить, что все, что реализует IBoolable, имеет свойство с именем MyBool, которое доступно только для чтения.

1 голос
/ 25 апреля 2011

Одним из решений является сделать MyProperty не абстрактным, а делегировать его реализацию абстрактному защищенному свойству, которое дочерние элементы должны переопределить:

public abstract class BaseClass
{
    public bool MyBool { get { return MyBoolInternal; } }
    protected abstract bool MyBoolInternal { get; set; }
}

public class ChildClass : BaseClass
{
    protected override bool MyBoolInternal { get; set; }
}
0 голосов
/ 25 апреля 2011

Чтобы оставить неоднозначным, хотите ли вы, чтобы установщик в унаследованных классах нарушал принципы ООП - то есть, если класс (абстрактный или нет) имеет открытый / защищенный установщик (абстрактный или нет), то все наследующие классы должны также;если класс этого не делает, то наследовать классы не следует.

Еще один способ подумать об этом - рассмотреть свойства, такие, что чтение и запись только для чтения является частью контракта класса.Поскольку экземпляры наследующих классов должны придерживаться отношения «Is-a» ( LSP ), наследующие классы не могут «добавить установщик» там, где его не было у основного класса, поскольку тот факт, что основнойкласс имел свойство без, так как сеттер является частью определения основного класса.Фактически, поскольку основной класс не может изменить рассматриваемое свойство с помощью установщика, поэтому все наследующие классы ДОЛЖНЫ гарантировать одинаковое поведение.

Рассмотрите возможность использования защищенного вспомогательного поля;затем вы можете разделить это свойство на свойство только для чтения и отдельный метод установки.Тогда у основного класса может быть только свойство, а у подкласса может быть метод установки , о котором главный класс не знает.Тем не менее, я не уверен, что это был бы хороший дизайн.

0 голосов
/ 25 апреля 2011

Вы должны решить, какое поведение вы хотите: если оно определено как абстрактное, тогда его должен ДОЛЖЕН реализовать производный класс.

Итак, что вы должны сделать, это:

public abstract class BaseClass
{
    public abstract string MyProperty { get; set; }
}


public class DerivedClass : BaseClass
{
    public override string MyProperty
    {
        get { return "myValue"; }
        set { /* do nothing, not applicable for this class */ }
    } 
}

Не выбрасывайте NotImplementedException - это не то, что вам нужно, вы просто хотите, чтобы установщик ничего не делал для некоторых дочерних классов.

...