Добавление сеттеров к свойствам в переопределениях - PullRequest
16 голосов
/ 19 мая 2011

Почему разрешено изменять видимость и существование геттеров или сеттеров в свойстве при реализации интерфейса?

interface IFoo
{
    string Bar { get; }
}

class RealFoo : IFoo
{
    public RealFoo(string bar)
    {
        this.Bar = bar;
    }

    public string Bar { get; private set; }
}

class StubFoo : IFoo
{
    public string Bar { get; set; }
}

... и не разрешено делать то же самое при реализации абстрактного класса?

abstract class AbstractFoo : IFoo
{
    public abstract string Bar { get; }
}

class RealFoo : AbstractFoo
{
    public RealFoo(string bar)
    {
        this.Bar = bar;
    }

    // Cannot override because 'Bar' does not have an overridable set accessor
    public override string Bar { get; private set; }
}

Ответы [ 4 ]

12 голосов
/ 19 мая 2011

Интерфейс объявляет, какие общедоступные свойства должен иметь класс (это просто контракт).Это означает, что вы должны иметь эти свойства, но можете добавить к ним.

Абстрактный класс объявляет фактическую структуру этих свойств.Поэтому, если у вас нет сеттера в абстрактной базе, вы не можете добавить его в реализацию.
Когда вы пишете модификатор переопределения, он ищет в базовом классе что-то для переопределения.

7 голосов
/ 19 мая 2011

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

В случае интерфейса вы определяете это:

interface IFoo
{
    string GetBar();
}

Какиеможет читаться как «все классы, которые реализуют этот интерфейс , должны включать этот метод».Оба ваших класса делают:

class RealFoo : IFoo
{
    public string GetBar();
    private void SetBar(string value);
}

они также реализуют SetBar (), но это несущественно;они выполнили контракт, определенный интерфейсом, и являются действительными.

С другой стороны, абстрактный класс выглядит так:

abstract class AbstractFoo : IFoo
{
    public abstract string GetBar();
}

Это означает, что все дочерние классы должны предоставлять тело методадля GetBar ()

Созданный вами класс выглядит следующим образом:

class RealFoo : AbstractFoo
{
    public override string GetBar();
    public override void SetBar(string value);
}

Поместив модификатор override перед методом SetBar, компилятор ожидает найти абстрактную или виртуальную версию вБазовый класс.У вас его нет, поэтому компиляция не удалась.

0 голосов
/ 19 мая 2011

Согласно спецификации C #

Аксессор, используемый для реализации интерфейса, может не иметь модификатора аксессора.Если для реализации интерфейса используется только один метод доступа, другой метод доступа может быть объявлен с модификатором доступа:

public interface I
{
  string Prop { get; }
}
public class C: I
{
  public Prop {
  get { return "April"; }     // Must not have a modifier here
        internal set {...}    // Ok, because I.Prop has no set accessor
  }
}

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

0 голосов
/ 19 мая 2011

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

Интерфейс, напротив, является полностью абстрактным набором членов, которые могут бытьмыслить как определение контракта на поведение.Реализация интерфейса остается полностью за разработчиком.

Взято с MSDN http://msdn.microsoft.com/en-us/library/scsyfw1d(v=VS.71).aspx

...