Переопределение Get, но не установлено

У меня есть абстрактный класс, который определяет get, но не set, потому что в отношении этого абстрактного класса ему требуется только get.

public abstract BaseClass
{
  public abstract double MyPop
  {get;}
}

Однако в некоторых классах-вывода мне нужно свойство set, поэтому я рассматриваю эту реализацию

public class DClass: BaseClass
{
  public override double MyPop
  {get;set;}
}

Проблема в том, что я получил ошибку компиляции, заявив, что

*. set: не может переопределить, потому что *. не имеет переопределяемого аксессуара.

Хотя я считаю, что вышеупомянутый синтаксис совершенно закончен.

Любая идея по этому поводу? Обходной путь или почему это так?

Изменить: Единственный подход, который я могу представить, - это поставить как get, так и set, как в абстрактном классе, и пусть подкласс выдает NotImplementedException, если set вызывается, а это не необходимо. Это что-то мне не нравится, а также специальный метод setter.

Ответ 1

Новое в С# 6.0:

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

void Main()
{
    BaseClass demo = new DClass(3.6);
}

public abstract class BaseClass
{
    public abstract double MyPop{ get; }
}

public class DClass : BaseClass
{
    public override double MyPop { get; }
    public DClass(double myPop) { MyPop = myPop;}
}

Ответ 2

Один из возможных ответов - переопределить getter, а затем реализовать отдельный метод setter. Если вы не хотите, чтобы определитель свойств был определен в базе, у вас не так много других параметров.

public override double MyPop
{
    get { return _myPop; }
}

public void SetMyPop(double value)
{
    _myPop = value;
}

Ответ 3

Невозможно делать то, что вы хотите. Вы должны определить сеттер в абстрактном свойстве, иначе вы не сможете его правильно переопределить.

Единственный случай, когда я знаю, где определяется геттер, и геттер/сеттер реализованы с помощью интерфейса:

public interface IBaseInterface
{
    double MyPop { get; }
}

public class DClass : IBaseInterface
{
    public double MyPop { get; set; }
}

Ответ 4

Если BaseClass находится в вашей собственной базе кода, вы можете сделать:

abstract public class BaseClass
{
    abstract public double MyPop { get; protected set; }
}

public class DClass : BaseClass
{
    private double _myProp;
    public override double MyProp
    {
        get { return _myProp; }
        protected set { _myProp = value; }
    }
}

EDIT: затем вы можете сделать общедоступный метод в DClass SetMyProp(double myProp) или тому подобное. Дизайн класса для вашей модели домена должен быть понятным или говорить сам за себя, почему вы не можете установить свойство непосредственно в базовом классе и почему вы можете сделать это в производном.

Ответ 5

Вы уверены, что выполнение того, что вы пытаетесь сделать, было бы хорошим дизайном, если бы вы нашли способ сделать это?

Это позволит объектам подкласса внести изменения состояния, которые не могут создать объекты родительского класса. Разве это не нарушит Принцип замещения Лискова?

Ответ 6

Вы можете сделать что-то вроде этого:

abstract class TestBase { public abstract int Int { get; } }

class TestDerivedHelper : TestBase
{
    private int _Int;
    public override int Int
    {
        get
        {
            return _Int;
        }
    }

    protected void SetInt(int value)
    {
        this._Int = value;
    }
}

class TestDerived : TestDerivedHelper
{
    public new int Int
    {
        get { return base.Int; }
        set { base.SetInt(value); }
    }
}

код >

Использование TestDerived будет иметь функциональность, которую вы ищете. Единственным недостатком, который я вижу из этого метода, является то, что вы должны реализовать каждый абстрактный метод в TestDerivedHelper, но он дает вам больше контроля позже.

Надеюсь, это поможет.;)

Ответ 7

Причина, по которой это невозможно, объясняется тем, что параметры "Магические" существуют С#. Когда вы определяете параметр, С# создает частное поле, в котором манипулируют неявный геттер и сеттер. Если в базовом классе нет сеттера, невозможно изменить эту переменную из метода, написанного в подклассе (поскольку частный флаг запрещает доступ к ним даже подклассам). Обычно обычно используется неявный установщик базового класса.

Я бы не советовал помещать набор в базовый класс, если не все под-классы могут это сделать, потому что это противоречит всему принципу полиморфного программирования (любой абстрактный метод, определенный в абстрактном классе, должен реализовываться подклассом), Создание специального метода setter, как описано в других ответах, вероятно, наилучшим образом.

Ответ 8

Блокада

abstract class TestBase
{
    public abstract int Int { get; }
}

class TestDerivedHelper : TestBase
{
    private int _Int;
    public override int Int
    {
        get
        {
            return _Int;
        }
    }

    protected void SetInt(int value)
    {
        this._Int = value;
    }
}

class TestDerived : TestDerivedHelper
{
    public new int Int
    {
        get { return base.Int; }
        set { base.SetInt(value); }
    }
}

Использование TestDerived будет иметь функциональность, которую вы ищете. Единственный недостаток, который я вижу из этого метода, - это то, что вы должны реализовать каждый абстрактный метод в TestDerivedHelper, но он дает вам больше позже.

Я использую этот подход и отлично работаю для меня. Кроме того, я тоже сделал свой тезис класса TestDerivedHelper, тогда все методы должны быть реализованы в классе "TestDerived".

Ответ 9

public abstract class BaseClass
{
    public abstract double MyPop { get; }
}

public class DClass: BaseClass
{
    private double _myPop = 0;
    public override double MyPop 
    {
        get { return _myPop; }
    }

    // some other methods here that use the _myPop field
}

Если вам нужно установить свойство извне DClass, возможно, было бы лучше поставить установщик в базовый класс.

Ответ 10

Несмотря на то, что этот поток устарел, я ставил свое решение, если оно помогает кому-то. Это не мое, но основано на ответах в других темах SO.

public abstract BaseClass
{
  public double MyPoP { get { return GetMyPoP; } }

  protected abstract double GetMyPoP { get; }
}

public class DClass: BaseClass
{
  public new double MyPoP { get; set; }

  protected override double GetMyPop { get { return MyPoP; } }
}

Это решение добавляет дополнительную строку кода для каждого такого свойства, для которого требуется модификация доступа. Тем не менее, нет изменений внешней видимости и обеспечивает необходимую функциональность.

Ответ 11

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

Ответ 12

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

Что вы можете сделать, это использовать ключевое слово new, чтобы скрыть реализацию базовых классов, но это может быть не то, что вы хотите.

Ответ 13

EDIT:

ОК Я, возможно, поспешил с этим ответом, но теперь я дал ему еще несколько соображений.

Вам нужно использовать абстрактный базовый класс? Если это не требуется, попробуйте следующее:

public interface ISomeRelevantName
{
    double MyPop { get; }
}

public class DClass : ISomeRelevantName
{
    public double MyPop { get; set; }
}