Почему не может интерфейсы C# содержать поля?

Например, предположите, что я хочу ICar взаимодействуйте через интерфейс и что все реализации будут содержать поле Year. Делает это означает, что каждая реализация должна отдельно объявить Year? Разве не было бы более хорошо просто определить это в интерфейсе?

217
задан Patrick Roberts 19 December 2018 в 12:15
поделиться

9 ответов

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

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

interface IFoo { void M(); } 
class Foo : IFoo { public void M() { ... } }

класс говорит: «Когда вы создаете из меня экземпляра, наполните ссылку на foo.m в слоте для ifoo.m.

Тогда, когда вы делаете вызов:

IFoo ifoo = new Foo();
ifoo.M();

Компилятор генерирует код Что говорит «Спросите объект, какой метод находится в слоте для IFOO.M, и вызовите этот метод.

Если интерфейс представляет собой набор слотов, которые содержат методы, то некоторые из этих слотов также могут содержать методы Get и Set и установки свойства, Get и Set Methods Indexer, а также методы удаления и удаления события Отказ Но поле не является методом . Там нет «слота», связанного с полем, которое вы можете затем «заполнить» со ссылкой на местоположение поля. И, следовательно, интерфейсы могут определять методы, свойства, индексаторы и события, но не поля.

230
ответ дан 23 November 2019 в 04:14
поделиться

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

В этом духе, интерфейсы C # позволяют определять свойства . Свойства, которые должны быть определены абоненты, которые должны предоставлять выполнение реализации:

interface ICar
{
    int Year { get; set; }
}

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

class Automobile : ICar
{
    public int Year { get; set; } // automatically implemented
}
130
ответ дан 23 November 2019 в 04:14
поделиться

Объявляйте его как недвижимость:

interface ICar {
   int Year { get; set; }
}
51
ответ дан 23 November 2019 в 04:14
поделиться

Почему бы не просто иметь год Свойство, которая идеально отлично?

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

Например, часть вашего Год Спецификация может потребовать, чтобы он был недействительным для ICAR реализаторов для обеспечения назначения год , который позже, чем текущий Год + 1 или до 1900 года. Нет способа сказать, что если вы выставили год , намного лучше использовать свойства вместо этого, чтобы выполнить работу здесь.

19
ответ дан 23 November 2019 в 04:14
поделиться

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

Рассмотрим этот сценарий, используя то, что вы предлагаете:

public interface InterfaceOne
{
    int myBackingVariable;

    int MyProperty { get { return myBackingVariable; } }
}

public interface InterfaceTwo
{
    int myBackingVariable;

    int MyProperty { get { return myBackingVariable; } }
}

public class MyClass : InterfaceOne, InterfaceTwo { }

У нас здесь есть пара проблем:

  • , потому что все члены интерфейса являются - по определению - общественности, наша вертенная переменная теперь подвергается всем, используя Интерфейс
  • , который MyBackingVariable будет MyClass MyClass Использование ?

Наиболее распространенный приемный подход - объявить интерфейс и Barebone абстрактного класса, который реализует его. Это позволяет вам гибкость либо наследовать из абстрактного класса и получить реализацию бесплатно или явно реализует интерфейс и допускается наследование от другого класса. Это работает что-то вроде этого:

public interface IMyInterface
{
    int MyProperty { get; set; }
}

public abstract class MyInterfaceBase : IMyInterface
{
    int myProperty;

    public int MyProperty
    {
        get { return myProperty; }
        set { myProperty = value; }
    }
}
18
ответ дан 23 November 2019 в 04:14
поделиться

Для этого вы можете иметь класс автомобильного базового класса, который реализует поле «Год», и все другие реализации могут наследовать от него.

0
ответ дан 23 November 2019 в 04:14
поделиться

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

Виртуальное ключевое слово реализуется в .NET с методами и так называемой V-таблицей, массивом указателей метода. Ключевое слово переопределения заполняет слоту V-Table с другим указателем метода, перезаписывая тот, который производится базовым классом. Свойства, события и индексаторы реализуются как методы под капотом. Но поля нет. Таким образом, интерфейсы могут не содержать поля.

35
ответ дан 23 November 2019 в 04:14
поделиться

Интерфейсы не содержат никакой реализации.

  1. Определите интерфейс с свойством.
  2. Далее вы можете реализовать этот интерфейс в любом классе и использовать этот класс, идущий вперед.
  3. Если требуется, вы можете иметь это свойство, определенное как виртуальное в классе, чтобы вы могли изменять его поведение.
3
ответ дан 23 November 2019 в 04:14
поделиться

Интерфейс определяет публично Свойства и методы экземпляра. Поля, как правило, являются частными или при наиболее защищенном, внутреннем или защищенном внутреннем (термин «поле» обычно не используется для ничего общего).

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

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

0
ответ дан 23 November 2019 в 04:14
поделиться
Другие вопросы по тегам:

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