Наследование интерфейса: возможно ли расширение свойств?

Я хочу сделать это:

interface IBase
{
    string Property1 { get; }
}

interface IInherited : IBase
{
    string Property1 { get; set; }
}

Чтобы у IInherited было унаследованное свойство Свойство Property1 ] с добавленной функциональностью, позволяющей установить .

Возможно ли это? Какой синтаксис?

РЕДАКТИРОВАТЬ: обратите внимание, я выделил слово «унаследовано» жирным шрифтом. Я спрашиваю конкретно о наследовании имущества, а не о том, чтобы скрыть его за новым.

25
задан kiamlaluno 18 August 2010 в 21:19
поделиться

6 ответов

Скрытие участника нарушает принцип замены Лискова, и в значительной степени этого делать не следует никогда. Скрывая этот член, вы вводите ошибку, которую очень сложно обнаружить, поскольку будут происходить 2 разных результата в зависимости от того, приводите ли вы объект как IBase1 или приводите его к IBase.

http: //en.wikipedia.org / wiki / Liskov_substitution_principle

2
ответ дан 28 November 2019 в 21:42
поделиться

Не явно, нет. У вас есть два варианта:

public interface IBase
{
    string Property1 { get; }
}

public interface IInherited : IBase
{
    void SetProperty1(string value);
}

Или вы можете просто отключить предупреждение компилятора с помощью ключевого слова new :

public interface IBase
{
    string Property1 { get; }
}

public interface IInherited : IBase
{
    new string Property1 { get; set; }
}

Если вы не реализуете IInherited.Property1 явно, IBase ] будет автоматически связываться с вашей устанавливаемой реализацией.

1
ответ дан 28 November 2019 в 21:42
поделиться

К сожалению, нет - свойства не могут быть расширены как таковые. Однако вы можете просто скрыть свойство с помощью new:

interface IInherited : IBase
{
    // The new is actually unnecessary (you get warnings though), hiding is automatic
    new string Property1 { get; set; }
}

Или вы можете создать свои собственные методы получения и установки, которые можно переопределить (старый добрый стиль Java):

interface IBase
{
    string GetProperty1();
}
interface IInherited : IBase
{
    void SetProperty1(string str);
}

Свойства фактически преобразуются в методы получения и установки компилятором.

1
ответ дан 28 November 2019 в 21:42
поделиться

Ваш код все равно должен работать ... он просто создает предупреждение компилятора из-за того, что скрывает Property1. Чтобы убрать это предупреждение, отметьте Свойство 1 в II, унаследованное с новым префиксом

1
ответ дан 28 November 2019 в 21:42
поделиться

Вы можете либо пометить свойство ключевым словом "new", либо пропустить наследование:

public interface IBase
{
    string Property1 { get; }
}

public interface IInherited : IBase
{
    new string Property1 { get; set; }
}

Или:

public interface IBase
{
    string Property1 { get; }
}

public interface IInherited
{
    string Property1 { get; set; }
}

В любом случае, это должно сработать:

public class SomeClass : IInherited, IBase
{
    public string Property1
    {
        get
        {
            // ...
        }
        set
        {
            // ...
        }
    }
}

Вы можете хорошенько подумать, прежде чем делать цепочку наследования для ваших интерфейсов. Кто какой интерфейс будет смотреть? Придется ли вам приводить к IInherited при передаче IBase? Если да, можете ли вы быть уверены, что сможете выполнить это приведение (если вы разрешите классы, созданные пользователем, тогда ответ будет отрицательным)? Этот вид наследования может серьезно повредить (повторному) удобству использования, если вы не будете осторожны.

0
ответ дан 28 November 2019 в 21:42
поделиться

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

Конечно, вы можете сказать, что IInherited "наследуется от" IBase; но что это на самом деле означает? Это интерфейсы; они устанавливают кодовые контракты. Скрывая свойство IBase.Property1 с помощью new string Property1 { get; set; }, вы не затеняете никакой функциональности. Таким образом, традиционная причина, по которой многие разработчики считают скрытие "плохой" вещью - что оно нарушает полиморфизм - в данном случае не имеет значения.

Спросите себя: что действительно важно, когда речь идет об интерфейсах? Они дают гарантию ответа на определенные вызовы методов, верно?

Итак, даны следующие два интерфейса:

interface IBase
{
    string Property1 { get; }
}

interface IInherited : IBase
{
    new string Property1 { set; }
}
  1. Если объект реализует IBase, вы можете прочитать его свойство Property1.
  2. Если объект реализует IInherited, вы можете читать его свойство Property1 (как и в случае реализации IBase), а также писать в него.

Опять же, здесь нет ничего проблематичного.

24
ответ дан 28 November 2019 в 21:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: