Подтвердить что ты не робот

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

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

interface IBase
{
    string Property1 { get; }
}

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

Итак, IInherited будет иметь свойство унаследованное Property1 с добавленной функциональностью, чтобы разрешить set.

Это возможно? Какой синтаксис?

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

4b9b3361

Ответ 1

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

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

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

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

interface IBase
{
    string Property1 { get; }
}

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

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

Ответ 2

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

Ответ 3

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

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 будет автоматически привязываться к вашей настраиваемой реализации.

Ответ 4

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

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

Или вы можете создавать собственные методы getter и setter, которые можно переопределить (хороший стиль Java):

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

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

Ответ 5

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

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

Ответ 6

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

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? Если да, можете ли вы гарантировать, что вы можете сделать это приведение (если вы разрешаете классы, созданные пользователем, тогда ответ отрицательный)? Такое наследование может действительно повредить (повтор) юзабилити, если вы не будете осторожны.