Наследование интерфейса - PullRequest
       10

Наследование интерфейса

9 голосов
/ 17 января 2009

Если у меня есть интерфейс:

interface IFoo
{
    int Offset {get;}
}

Могу ли я иметь это:

interface IBar: IFoo
{   
    int Offset {set;}
}

так что потребители IBar смогут установить или приобрести?

Ответы [ 5 ]

7 голосов
/ 17 января 2009

Нет, вы не можете!

(я собирался написать «Да», но, прочитав пост Энтони и попробовав несколько хитростей, я нашел ответ НЕТ!)

class FooBar : IFoo, IBar
{
    public int Offset{get;set;}
}

(сгенерирует предупреждение, как указывает Энтони, что можно исправить, добавив ключевое слово "new".)

При тестировании кода:

IBar a = new FooBar();
a.Offset = 2;
int b = a.Offset;

В последней строке будет сгенерирована ошибка компиляции, так как вы скрыли установщик смещения IBar.

РЕДАКТИРОВАТЬ: Исправлен модификатор accesibillity для свойства в классе. Спасибо Энтони!

7 голосов
/ 17 января 2009

Это близко, но без банана.

interface IFoo
{
    int Offset { get; }
}

interface IBar : IFoo
{
    new int Offset { set; }
}

class Thing : IBar
{
    public int Offset { get; set; }
}

Обратите внимание на ключевое слово new в IBar, но оно переопределяет метод доступа get IFoo, поэтому IBar не получает get. Следовательно, нет, вы не можете создать IBar, который просто добавляет набор, сохраняя при этом существующий get.

3 голосов
/ 17 января 2009

+ 1 к Арджану Эйнбу

Конечно, пользователи IBar не смогут получить значение свойства Offset, потому что наследование IFoo не меняет семантику свойства Offset, определенного в IBar - компилятор предупреждает вас по причине. При использовании «нового» ключевого слова компилятор полностью удаляет неоднозначность и обрабатывает IBar.Offset только для записи. Однако потребители класса , унаследованные от интерфейса IBar, смогут получить и установить свойство Offset.

Разница становится более заметной, если вы используете явную реализацию интерфейса:

class Boo: IBar
{
    int IFoo.Offset { get { return 0; } }
    int IBar.Offset 
    {
          set { }  // OK - IBar has a setter
          get { return 1; } // compiler error - IBar.Offset doesn't inherit setter

    }
}

class Program
{
    static void Main(string[] args)
    {
        Boo b = new Boo();
        int x = ((IFoo) b).Offset; // OK - IFoo.Offset has getter
        ((IBar) b).Offset = 1; // OK - IBar.Offset has setter
        x = ((IBar) b).Offset; // compiler error - IBar doesn't inherit 
                               // getter from IFoo
    }
}
2 голосов
/ 17 января 2009

То, что вы могли бы сделать, это иметь интерфейс IBar с геттером и сеттером (в действительности нет никакого смысла не иметь этого). Когда у вас есть только установщик в IBar, вы действительно явно говорите, что «на интерфейсе IBar свойство Offset - только запись», это явно не то, что вы хотите.

interface IFoo 
{ 
    int Offset { get;}
}

interface IBar : IFoo 
{
    new int Offset { get; set; } 
}

class Thing : IBar 
{
    public int Offset
    {
        get;
        set;
    }
}

Теперь вы можете использовать класс Thing следующим образом:

var t = new Thing();
t.Offset = 1;
int read = t.Offset;
0 голосов
/ 19 декабря 2011

Если бы получатели и установщики свойств были независимыми объектами, интерфейс, определяющий установщик свойства и унаследованный от того, который определял получатель свойства, позволял бы семантику чтения-записи. К сожалению, по какой-либо причине ни vb.net, ни C # не позволят этому работать. Вместо этого геттеры - это свойства только для чтения, а сеттеры - свойства только для записи. Если тип определяет свойство только для записи, но наследует свойство только для чтения, vb.net и C # будут видеть только свойство только для записи. Если интерфейс наследует интерфейс, который предоставляет свойство только для чтения, и интерфейс, который предоставляет свойство только для записи, ни одно из свойств не будет использоваться в интерфейсе, поскольку ни vb.net, ни C # не хотят использовать тот факт, что свойство используется чтение или запись, чтобы определить, использовать ли свойство только для чтения или только для записи. Вместо этого оба языка объявят, что свойство является «неоднозначным».

Как уже отмечалось, решение состоит в том, чтобы иметь интерфейс, который наследует интерфейс со свойством только для чтения и реализует свойство чтения-записи. Это скроет другое свойство только для чтения, но если свойство чтения-записи реализовано так, чтобы возвращать те же данные, это не должно быть проблемой. Действительно, способ, которым неявная реализация интерфейса обрабатывается в C #, позволяет реализовывать как интерфейс чтения-записи, так и интерфейс только для чтения, используя один и тот же код (vb, несколько досадно, требует, чтобы свойство «только чтение» кодировалось отдельно от свойство 'read-write').

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