Почему интерфейсы предпочтены абстрактным классам?

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

b = Button(admin, text='as', command=lambda: button('hey'))

См. раздел «Передача аргументов в обратные вызовы» в этом документе .

35
задан Michael Myers 12 March 2009 в 21:24
поделиться

20 ответов

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

  1. Дают им ответ, который они хотят.
  2. Почтительно не соглашаются.

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

Однако, если Вы создаете принуждение (и корректный) аргумент в Вашем разногласии, тогда интервьюер мог бы обратить внимание. Во-первых, выделите положительные моменты об интерфейсах, это - НЕОБХОДИМОСТЬ. Во-вторых, я сказал бы, что интерфейсы лучше во многих сценариях, но они также ведут для кодирования дублирования, которое является отрицательным моментом. Если у Вас есть огромное количество подклассов, которые будут делать в основном ту же реализацию плюс дополнительная функциональность, то Вы могли бы хотеть абстрактный класс. Это позволяет Вам иметь много подобных объектов с мелкомодульной деталью, тогда как с только взаимодействует через интерфейс, у Вас должно быть много отдельных объектов почти с дублирующим кодом.

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

55
ответ дан DevinB 10 October 2019 в 11:17
поделиться

Ну, я предложил бы, чтобы сам вопрос был перефразирован. Интерфейсы являются главным образом контрактами, которые получает класс, реализация того контракта самого будет варьироваться. Абстрактный класс будет обычно содержать некоторую логику умолчания, и ее дочерние классы добавят еще некоторую логику. Я сказал бы, что ответ на вопросы полагается на ромбовидную проблему. Java предотвращает множественное наследование для предотвращения его. ( http://en.wikipedia.org/wiki/Diamond_problem ).

0
ответ дан Yorch 10 October 2019 в 11:17
поделиться

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

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

0
ответ дан Chochos 10 October 2019 в 11:17
поделиться

Поскольку интерфейсы не вынуждают Вас в некоторую иерархию наследования.

0
ответ дан Marko 10 October 2019 в 11:17
поделиться

Существует одна причина, не упомянутая вышеупомянутым.

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

См. http://tutorials.jenkov.com/java-reflection/dynamic-proxies.html для учебного руководства.

1
ответ дан Thorbjørn Ravn Andersen 10 October 2019 в 11:17
поделиться

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

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

3
ответ дан krosenvold 10 October 2019 в 11:17
поделиться

, "Почему Интерфейсы предпочтены по Абстрактным классам?"

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

, Но рассмотрение вопроса об интервью, лучший вопрос действительно" , Когда интерфейсы должны быть предпочтены по абстрактным классам?" (и наоборот).

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

3
ответ дан Neal Stublen 10 October 2019 в 11:17
поделиться

Абстрактные классы используются, когда Вы наследовались реализация , интерфейсы используются, когда Вы наследовались спецификация . В стандартах JDBC говорится, что "Соединение должно сделать это ". Это - спецификация.

4
ответ дан paulmurray 10 October 2019 в 11:17
поделиться

Абстрактные классы имеют много потенциальных ловушек. Например, при переопределении метода, super(), метод не называют, если Вы явно не называете его. Это может вызвать проблемы для плохо реализованных переопределяющих классов. Кроме того, существуют потенциальные проблемы с equals() при использовании наследования.

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

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

кроме того, как Вы упоминаете, можно только расширить один класс за один раз, но можно реализовать столько интерфейсов, сколько Вы желаете.

5
ответ дан Eddie 10 October 2019 в 11:17
поделиться

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

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

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

7
ответ дан Community 10 October 2019 в 11:17
поделиться

Абстрактные классы

1. Не может быть инстанцирован независимо от их производных классов. Конструкторов абстрактного класса вызывают только их производные классы.

2. Определите абстрактные членские подписи, которые должны реализовать базовые классы.

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

4. Может включать данные, хранившие в поля.

5. Допускайте (виртуальных) участников, которые имеют реализацию и, поэтому, обеспечивают реализацию по умолчанию участника к происходящему классу.

6. Получение из абстрактного класса израсходовало один подкласса и только опцию базового класса.

Интерфейс

1. Не может быть инстанцирован.

2. Реализация всех членов интерфейса происходит в базовом классе. Не возможно реализовать только некоторых участников в классе с реализацией.

3. Расширение интерфейсов с дополнительными участниками повреждает совместимость версий.

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

5. Все участники являются автоматически виртуальными и не могут включать реализацию.

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

10
ответ дан Warrior 10 October 2019 в 11:17
поделиться

Можно реализовать больше чем один интерфейс, но можно только наследоваться единому классу

10
ответ дан Rowland Shaw 10 October 2019 в 11:17
поделиться

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

23
ответ дан Joel Coehoorn 10 October 2019 в 11:17
поделиться

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

interface
   abstract class
       concrete class 1       
       concrete class 2

интерфейс там по нескольким причинам:

  • существующий класс, который уже расширяет что-то, может реализовать интерфейс (предположение, что Вы управляете кодом для существующего класса)
  • , существующий класс может быть подклассами, и подкласс может реализовать интерфейс (предположение, что существующий класс является подподдающимся классификации)

, Это означает, что можно посещать существующие ранее уроки (или просто классы, которые ДОЛЖНЫ расшириться от чего-то еще), и сделайте, чтобы они работали с кодом.

абстрактный класс там для обеспечения всех общих битов для реальных классов. Абстрактный класс расширяется от того, когда Вы пишете новые классы или изменяете классы, что Вы хотите расширить его (предположение, что они расширяются от java.lang. Объект).

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

24
ответ дан TofuBeer 10 October 2019 в 11:17
поделиться

interface с являются более чистым способом записать чисто абстрактный класс. Можно сказать, что реализация не кралась в (конечно, Вы могли бы хотеть сделать это на определенных этапах обслуживания, которое делает интерфейсы плохо). Это об этом. Нет почти никакого различия, заметного к клиентскому коду.

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

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

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

1
ответ дан Tom Hawtin - tackline 10 October 2019 в 11:17
поделиться

Почтительно не согласитесь с большинством вышеупомянутых плакатов (извините! модификация меня вниз, если Вы хотите:-))

<час>

Первый, "только одним суперклассом" ответ является Ламе. Любой, кто дал мне, что на ответ в интервью быстро ответят "C++, существовал, прежде чем Java и C++ имели несколько суперклассов. Почему Вы думаете, что James Gosling только позволил один суперкласс для Java?"

Понимают философию позади Вашего ответа иначе, Вы - тост (по крайней мере, если я беру интервью у Вас.)

118-секундный <час>, интерфейсы имеют несколько преимуществ перед абстрактными классами, особенно при разработке интерфейсов. Самый большой не имеет конкретной структуры класса, наложенной на вызывающую сторону метода. Нет ничего худшего, чем попытка использовать вызов метода, который требует конкретную структуру класса. Это является болезненным и неловким. Используя интерфейс что-либо может быть передано методу с минимумом ожиданий.

Пример:

public void foo(Hashtable bar);

по сравнению с [1 110]

public void foo(Map bar);

Для первого, вызывающая сторона будет всегда брать их существующую структуру данных и сбрасывать ее на новую Хеш-таблицу.

<час>

В-третьих, интерфейсы позволяют открытые методы в реализаторах реального класса быть "частными". Если метод не объявляется в интерфейсе тогда, метод не может использоваться (или неправильно использоваться) классами, которые не имеют никакого бизнеса с помощью метода. Который приносит мне для указания 4....

<час>

Четвертый, Интерфейсы представляют минимальный контракт между классом с реализацией и вызывающей стороной. Этот минимальный контракт определяет точно , как конкретный реализатор ожидает использоваться и не больше. Классу вызова не позволяют использовать никакой другой метод, не определенный "контрактом" интерфейса. Имя интерфейса, используемое также разновидности ожидание разработчика того, как они должны использовать объект. Если разработчик передается

public interface FragmentVisitor {
    public void visit(Node node);
}

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

<час>

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

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

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

<час>

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

3
ответ дан Pat 10 October 2019 в 11:17
поделиться

Можно реализовать несколько интерфейсов, но особенно с c# у Вас не может быть множественных наследований

0
ответ дан user68610 10 October 2019 в 11:17
поделиться

Они попросили меня взять любой из API JDBC что вы используете. «Почему они Интерфейсы? ".

Мой ответ на этот конкретный вопрос таков:

SUN не знает, как их реализовать или что внедрить в реализацию. Поставщики услуг / поставщики БД должны внедрять свою логику в реализацию.

Проект JDBC связан с шаблоном Bridge, который гласит: «Отсоедините абстракцию от своей реализации, чтобы они могли варьироваться независимо».

Это означает, что иерархия интерфейсов API JDBC api может развиваться независимо от иерархии реализации, что Поставщик jdbc предоставляет или использует.

0
ответ дан Manoj 27 November 2019 в 06:23
поделиться

Abstract classes offer a way to define a template of behavior, where the user plugins in the details.

One good example is Java 6's SwingWorker. It defines a framework to do something in the background, requiring the user to define doInBackground() for the actual task.

I extended this class such that it automatically created a popup progress bar. I overrode done(), to control disposal of this pop-up, but then provided a new override point, allowing the user to optionally define what happens after the progress bar disappears.

public abstract class ProgressiveSwingWorker<T, V> extends SwingWorker<T, V> {

    private JFrame progress;

    public ProgressiveSwingWorker(final String title, final String label) {
        SwingUtilities.invokeLater(new Runnable() {
            @SuppressWarnings("serial")
            @Override
            public void run() {
                progress = new JFrame() {{
                    setLayout(new MigLayout("","[grow]"));
                    setTitle(title);
                    add(new JLabel(label));
                    JProgressBar bar = new JProgressBar();
                    bar.setIndeterminate(true);
                    add(bar);
                    pack();
                    setLocationRelativeTo(null);
                    setVisible(true);
                }};
            }
        });
    }

    /**
     * This method has been marked final to secure disposing of the progress dialog. Any behavior
     * intended for this should be put in afterProgressBarDisposed.
     */
    @Override
    protected final void done() {
        progress.dispose();
        try {
            afterProgressBarDisposed(get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

    protected void afterProgressBarDisposed(T results) {
    }

}

The user still has the requirement of providing the implementation of doInBackground(). However, they can also have follow-up behavior, such as opening another window, displaying a JOptionPane with results, or simply do nothing.

To use it:

new ProgressiveSwingWorker<DataResultType, Object>("Editing some data", "Editing " + data.getSource()) {

    @Override
    protected DataResultType doInBackground() throws Exception {
        return retrieve(data.getSource());
    }

    @Override
    protected void afterProgressBarDisposed(DataResultType results) {
        new DataEditor(results);
    }

}.execute();

This shows how an abstract class can nicely provide a templated operation, orthogonal to the concept of interfaces defining an API contract.

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

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

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

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