Почему C # не позволяет статическим методам реализовать интерфейс? - PullRequest
429 голосов
/ 03 ноября 2008

Почему C # был разработан таким образом?

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

Если классы хотят реализовать это поведение в общем методе, почему бы и нет?

Вот пример того, что я имею в виду:

// These items will be displayed in a list on the screen.
public interface IListItem {
  string ScreenName();
  ...
}

public class Animal: IListItem {
    // All animals will be called "Animal".
    public static string ScreenName() {
        return "Animal";
    }
....
}

public class Person: IListItem {

    private string name;

    // All persons will be called by their individual names.
    public string ScreenName() {
        return name;
    }

    ....

 }

Ответы [ 25 ]

3 голосов
/ 03 ноября 2008

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

3 голосов
/ 03 ноября 2008

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

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

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

3 голосов
/ 03 ноября 2008

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

1 голос
/ 15 июля 2013

Большинство людей, кажется, забывают, что в ООП классы тоже являются объектами, и поэтому у них есть сообщения, которые по какой-то причине c # называет «статическим методом». Тот факт, что существуют различия между объектами экземпляра и объектами класса, показывает только недостатки или недостатки в языке. Оптимист о c # хотя ...

1 голос
/ 03 ноября 2008

К вашему сведению: вы можете получить поведение, похожее на то, что вы хотите, создав методы расширения для интерфейса. Метод расширения будет общим, не переопределяемым статическим поведением. Однако, к сожалению, этот статический метод не будет частью контракта.

1 голос
/ 03 ноября 2008

Интерфейсы - это абстрактные наборы определенных доступных функций.

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

Если бы методы были определены как статические, класс, реализующий интерфейс, не был бы настолько инкапсулирован, как мог бы. Инкапсуляция - хорошая вещь, к которой нужно стремиться в объектно-ориентированном проектировании (я не буду вдаваться в причину, вы можете прочитать это здесь: http://en.wikipedia.org/wiki/Object-oriented). По этой причине статические методы не допускаются в интерфейсах.

1 голос
/ 29 июля 2013

ОК, вот пример необходимости 'метода типа'. Я создаю один из набора классов на основе исходного XML. Итак, у меня есть

  static public bool IsHandled(XElement xml)

функция, которая вызывается по очереди для каждого класса.

Функция должна быть статической, так как в противном случае мы тратим время на создание неподходящих объектов. Как отмечает @Ian Boyde, это можно сделать на фабричном классе, но это только добавляет сложности.

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

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

Таким образом, это небольшая потенциальная особенность, которую, вероятно, лучше всего не учитывать.

1 голос
/ 19 января 2011

Статические классы должны быть в состоянии сделать это, чтобы их можно было использовать в общем. Вместо этого мне пришлось реализовать Singleton для достижения желаемых результатов.

У меня было несколько классов Static Business Layer, в которых реализованы такие методы CRUD, как «Создать», «Чтение», «Обновление», «Удалить» для каждого типа сущности, например «Пользователь», «Команда» и т. Д. создал базовый элемент управления с абстрактным свойством для класса бизнес-уровня, в котором реализованы методы CRUD. Это позволило мне автоматизировать операции «Создать», «Чтение», «Обновить», «Удалить» из базового класса. Мне пришлось использовать Синглтон из-за статического ограничения.

1 голос
/ 19 января 2016

C # и CLR должны поддерживать статические методы в интерфейсах, как это делает Java. Модификатор static является частью определения контракта и имеет значение, в частности то, что поведение и возвращаемое значение не меняются в зависимости от экземпляра, хотя оно все еще может варьироваться от вызова к вызову.

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

1 голос
/ 26 июля 2015

Тот факт, что статический класс реализован в C # Microsoft, создавая специальный экземпляр класса со статическими элементами, является просто странностью того, как достигается статическая функциональность. Это не теоретический момент.

Интерфейс ДОЛЖЕН быть дескриптором интерфейса класса - или того, как с ним взаимодействуют, и это должно включать статические взаимодействия. Общее определение интерфейса (от Meriam-Webster): место или область, в которой разные вещи встречаются, общаются или влияют друг на друга. Когда вы полностью опускаете статические компоненты класса или статические классы, мы игнорируем большие разделы взаимодействия этих плохих парней.

Вот очень четкий пример того, где было бы весьма полезно использовать интерфейсы со статическими классами:

public interface ICrudModel<T, Tk>
{
    Boolean Create(T obj);
    T Retrieve(Tk key);
    Boolean Update(T obj);
    Boolean Delete(T obj);
}

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

...