Добавление метода доступа к свойству интерфейса разрешено, но не для абстрагирования свойства - PullRequest
5 голосов
/ 20 февраля 2012

Почему допустимо следующее C #:

public interface ISomeInterface
{
    int SomeProperty
    {
        get;
    }
}

public class SomeClassImplementingInterface : ISomeInterface
{
    public int SomeProperty
    {
        get { return 32; }
        protected set {}
    }
}

, но это не так:

public abstract class SomeAbstractClass
{
    public abstract int SomeProperty
    {
        get;
    }
}

public class SomeClassExtendingAbstractClass : SomeAbstractClass
{
    public override int SomeProperty
    {
        get { return 32; }
        protected set {}
    }
}

Последнее приводит к следующей ошибке во время компиляции:

'InterfaceAbstractTest.SomeClassExtendingAbstractClass.SomeProperty.set': не может переопределить, потому что 'InterfaceAbstractTest.SomeAbstractClass.SomeProperty' не имеет переопределенного метода доступа к множеству InterfaceAbstractTest

по каким-либо причинампоследний, в то время как позволяет первый?

Ответы [ 5 ]

3 голосов
/ 20 февраля 2012

Поскольку вызывающий объект, использующий интерфейс, заботится только о том, чтобы разработчик интерфейса по крайней мере реализовал определение интерфейса, как говорится в @davisoa, тогда как SomeAbstractClass в вашем примере определяет публичный контракт, в котором точно указывается тип, доступность и (для свойств) читаемость / возможность записи членов.

Если вы используете отражение, чтобы получить PropertyInfo SomeProperty (из базового или дочернего класса), он должен разрешить эту информацию откуда-то. Разрешение дочернему классу изменять читаемость / возможность записи будет таким же нарушением договора, как и изменение типа возвращаемого значения или списка аргументов.

Представьте себе, например:

SomeAbstractClass sc = new SomeClassExtendingAbstractClass();
PropertyInfo pi = sc.GetType().GetProperty("SomeProperty");
Console.Out.WriteLine(pi.CanWrite); // What should be printed here?
2 голосов
/ 20 февраля 2012

Это потому, что реализация интерфейса обещает, что будет свойство SomeProperty, которое вы можете "получить".

Реализация абстрактного класса обещает, что его дочерние классы предоставят реализацию свойства SomeProperty с открытым методом get.

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

1 голос
/ 20 февраля 2012

Это по замыслу. Я цитирую из спецификации языка C #:

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

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

1 голос
/ 20 февраля 2012

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

0 голосов
/ 20 февраля 2012

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...