Squeak.ru - шаблоны программирования

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

Недавно я присутствовал на собеседовании, и мне задали вопрос: «Почему интерфейсы предпочтительнее абстрактных классов?»

Я попытался дать несколько ответов, например:

  • Мы можем получить только один расширенный функционал
  • они на 100% абстрактны
  • Реализация не жестко закодирована

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

Могу ли я получить лучший ответ для этого?


  • Я почти уверен, что видел подобный вопрос раньше, но даже Google не может его найти. Может быть, мой разум снова играет со мной злые шутки. 12.03.2009
  • Примечание. Я отредактировал заголовок по грамматике; Я оставил тело, так как это, кажется, цитаты, и, возможно, они действительно говорили это так. 12.03.2009
  • Это нагруженный вопрос, поскольку он предполагает позицию по теме и не дает контекста, в котором он «может быть» действительным. Я согласен с devinb в этом. Они оба являются инструментами — используйте их надлежащим образом. Слишком много ответов здесь оправдывают вопрос... что может быть приемлемо, если вы действительно хотите получить эту работу. 12.03.2009
  • Не оправдывайте вопрос ответом. Это не то, что они (ну, должно быть) ищут. Покажите, что вы знаете, о чем говорите, и можете выполнять работу. Если им стоит работать, они не ищут попугая. 13.03.2009
  • См. мой полный комментарий ниже ... но каждый раз, когда я получаю ответ, подобный вашему, кандидат получает холодное спасибо за уделенное время. Ответ не показывает глубины понимания. 15.03.2009
  • Начните писать тестовые наборы или идите по пути TDD, и вы обнаружите, что писать тестовые наборы намного проще при использовании интерфейсов. Это позволяет вам смоделировать все, что вам не нужно для вашего тестового примера. 25.11.2009
  • возможный дубликат Interface vs Abstract Class (общий OO) 01.07.2013
  • Возможный дубликат Когда использовать интерфейс вместо абстрактного класса и наоборот? 18.09.2016

Ответы:


1

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

  1. Дайте им ответ, который они хотят.
  2. С уважением не согласен.

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

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

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

12.03.2009
  • Если вы со всем уважением не согласны, я думаю, вы почти наверняка упустили шанс получить работу. 12.03.2009
  • Если ваш интервьюер недалекий и не желает слышать альтернативную точку зрения, я бы не хотел эту работу. Пока вы ведете себя уважительно (и понимаете субординацию), вы должны быть в состоянии высказать обоснованное, вдумчивое мнение и не быть за это наказанным. 12.03.2009
  • Я бы +1 больше, чем один раз, если бы мог. Единственный ответ, который я видел до сих пор, который (соответственно) ставит под сомнение вопрос. Лучше было бы спросить, когда интерфейсы предпочтительнее абстрактных классов, или назвать плюсы и минусы интерфейсов и абстрактных классов. 12.03.2009
  • @ Том, в зависимости от того, как вы это представите, это не должно стоить вам шанса на работу. С другой стороны, если это так, то, возможно, вы все равно не хотели там работать :-) 12.03.2009
  • Этот вопрос не означает, что это то, во что верит интервьюер. Они могут думать по-другому, но хотят увидеть, согласны ли вы с ними или у вас есть бутылка, чтобы оспорить вопрос. Обычно на загруженные вопросы нужно отвечать, когда вакансия является конкурентоспособной. 29.03.2009
  • Интерфейсы не приведут к дублированию кода, если у вас есть два объекта с одинаковой функциональностью, что предполагает одинаковый API и, следовательно, одинаковый интерфейс. Абстрактные классы — это детали реализации, а интерфейсы — это общий контракт, который вы предоставляете программисту, используя свой API. 22.09.2013
  • Проблема с этим решением в том, что вы прочитали вопрос со своим эго. Интервьюер спросил, почему его предпочитают, а не почему его предпочитают все время. 08.06.2019

  • 2

    В общем, и это ни в коем случае не «правило», которому следует слепо следовать, самая гибкая договоренность такова:

    interface
       abstract class
           concrete class 1       
           concrete class 2
    

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

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

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

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

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

    12.03.2009
  • Хорошо сказано. Интерфейсы и классы списков и коллекций имеют множество примеров этого. 12.03.2009
  • Это очень мощный и гибкий паттерн. Я видел, как он часто используется в фреймворках. По сути, абстрактный класс обеспечивает «каркасную» реализацию интерфейса. 13.03.2009
  • Возможно, стоит отметить, что (1) любой конкретный класс, наследующий от абстрактного класса, не может наследовать ни от чего другого — ограничение, которое может показаться маловероятным, но могло бы быть; возможность реализации интерфейса напрямую обеспечивает предохранительный клапан на случай возникновения ситуации, когда наследование классов будет проблематичным; (2) классы, реализующие интерфейс напрямую, будут изменены при изменении интерфейса; если базовый класс может делать такие вещи, как предлагать реализацию новых методов по умолчанию, производные от него классы, возможно, не должны изменяться. 31.10.2012
  • Если в итоге получается интерфейс, который реализуется непосредственно тремя классами (включая абстрактный базовый класс), и этот базовый класс наследуется дюжиной других классов, добавление промежуточного уровня может означать, что изменение интерфейса требует исправления трех классов, а не чем четырнадцать. Довольно крупная победа. Однако стоит отметить, что такие вещи, как переменные и места хранения, должны быть объявлены как относящиеся к типу интерфейса, а не к абстрактному типу, чтобы позволить классам, реализующим интерфейс, напрямую взаимодействовать с теми, которые наследуют абстрактную базу. 31.10.2012

  • 3

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

    12.03.2009
  • Привет, это правда. Но он все еще может наследовать интерфейс, не так ли? 31.05.2010
  • Techmaddy уже указывал на это в вопросе: мы можем получить только одну расширенную функциональность. 09.05.2011

  • 4

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

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

  • 5

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

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

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

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

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

    5. Разрешить (виртуальные) члены, которые имеют реализацию и, следовательно, предоставить реализацию члена по умолчанию для производного класса.

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

    Интерфейс

    1. Невозможно создать экземпляр.

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

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

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

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

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

    12.03.2009

    6

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

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

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

    12.03.2009

    7

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

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

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

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

    12.03.2009

    8

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

    15.03.2009

    9

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

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

    12.03.2009

    10

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

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

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

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

    12.03.2009

    11

    Со всем уважением не согласен с большинством вышеприведенных плакатов (извините! Модифицируйте меня, если хотите :-))


    Во-первых, ответ «только один суперкласс» неубедителен. Любой, кто дал бы мне такой ответ в интервью, быстро бы возразил: «C++ существовал до того, как Java, а C++ имел несколько суперклассов. Как вы думаете, почему Джеймс Гослинг разрешил только один суперкласс для Java?»

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


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

    Пример:

    public void foo(Hashtable bar);
    

    vs.

    public void foo(Map bar);
    

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


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


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

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

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


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

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

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


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

    15.03.2009
  • Вопрос, на который вы бы ответили, лучше оригинала, ИМХО, хотя его можно было бы сформулировать с точки зрения многих последних языков и фреймворков, а не Java, в частности. Хотя .net заимствует некоторые довольно глупые вещи из Java (например, представление о том, что числа с плавающей запятой должны неявно преобразовываться в двойные, а не наоборот, когда преобразования с плавающей запятой в двойное с большей вероятностью будут ошибочными), я не думаю, что .net имеет одиночное наследование просто потому, что это делает Java. Наследование полезно как для объединения кода/данных, так и для заменяемости. Обмен кодом/данными часто более удобен с... 26.02.2012
  • ... наследование, чем с композицией, хотя это может быть достигнуто в любом случае. Разрешение формы множественного наследования, которая включает совместное использование кода/данных, создает трудности (например, проблема алмаза). Поскольку множественное наследование кода/данных не допускает многого, чего нельзя было бы достичь с помощью композиции, но возможность замещения множества других вещей, не связанных друг с другом, очень полезна, имеет смысл предложить что-то, что подобно наследованию, но ограничен последней функциональностью. 26.02.2012
  • (Кстати, относительно чисел с плавающей запятой и удвоения, умножение двух чисел с плавающей запятой, которые равны 1E38, а затем преобразование результата в число с плавающей запятой, даст ответ, означающий, что число равно большому для числа с плавающей запятой, что будет правильным. Умножение двух чисел с плавающей запятой, равных 1E38, а затем приведя результат к двойному, ответ будет слишком большим для двойного, что будет неправильным. 26.02.2012

  • 12

    Если они думают, что X лучше, чем Y, я бы не беспокоился о том, чтобы получить работу, я бы не хотел работать на кого-то, кто заставляет меня предпочесть один дизайн другому, потому что им сказали, что интерфейсы лучше. Оба хороши в зависимости от ситуации, иначе почему язык решил добавить абстрактные классы? Конечно, разработчики языка умнее меня.

    30.07.2011

    13

    Это проблема «множественного наследования». Мы можем «расширять» не более одного абстрактного класса одновременно через другой класс, но в интерфейсах мы можем «реализовать» несколько интерфейсов в одном классе. Итак, хотя Java вообще не обеспечивает множественного наследования, но с помощью интерфейсов мы можем включить в него свойство множественного наследования.

    Надеюсь это поможет!!!

    03.12.2012

    14

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

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

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

    С другой стороны, для интерфейсов компилятор не может уловить некоторые невозможные приведения /instanceof.

    12.03.2009

    15

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

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

    См. http://tutorials.jenkov.com/java-reflection/dynamic-proxy.html для руководства.

    12.03.2009

    16

    интерфейс не заменяет абстрактный класс.

    Предпочтение

    интерфейс: для реализации контракта несколькими несвязанными объектами.

    абстрактный класс: для реализации одинакового или различного поведения нескольких связанных объектов.


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

    Интерфейс и абстрактный класс (общий OO)

    Случай использования:

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

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

    07.11.2016

    17

    Вы можете реализовать несколько интерфейсов, но, в частности, с С# вы не можете иметь множественное наследование

    12.03.2009

    18

    Потому что интерфейсы не принуждают вас к какой-то иерархии наследования.

    12.03.2009

    19

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

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

    12.03.2009
  • Итак, если бы JDBC был полностью абстрактным классом, чем бы это отличалось? (Не говоря уже о том, что интерфейсы изменились между выпусками.) 12.03.2009
  • @ Том Хотин: я сказал то же самое, и они спросили, что спросил Том Хотин. 12.03.2009
  • Если бы это были абстрактные классы, а не интерфейсы, это могло бы быть быстрее в зависимости от виртуальной машины, и это заставляло бы разработчиков расширяться только от классов, которые были им даны как часть библиотек java.sql, что могло бы ограничивать. 13.03.2009

  • 20

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

    12.03.2009

    21

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

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

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

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

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

    13.04.2009

    22

    Абстрактные классы предлагают способ определить шаблон поведения, в который пользователь встраивает детали.

    Одним из хороших примеров является SwingWorker в Java 6. Он определяет структуру для выполнения каких-либо действий в фоновом режиме, требуя от пользователя определения doInBackground() для фактической задачи.

    Я расширил этот класс таким образом, чтобы он автоматически создавал всплывающую полосу прогресса. Я переопределил done(), чтобы управлять удалением этого всплывающего окна, но затем предоставил новую точку переопределения, позволяющую пользователю дополнительно определять, что происходит после исчезновения индикатора выполнения.

    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) {
        }
    
    }
    

    Пользователь по-прежнему должен предоставить реализацию doInBackground(). Однако они также могут иметь последующее поведение, например открывать другое окно, отображать JOptionPane с результатами или просто ничего не делать.

    Чтобы использовать его:

    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();
    

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

    21.10.2009

    23

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

    25.11.2009
    Новые материалы

    Угловая структура архитектуры
    Обратите внимание, что эта статья устарела, я решил создать новую с лучшей структурой и с учетом автономных компонентов: https://medium.com/@marekpanti/angular-standalone-architecture-b645edd0d54a..

    «Данные, которые большинство людей используют для обучения своих моделей искусственного интеллекта, поставляются со встроенным…
    Первоначально опубликовано HalkTalks: https://hacktown.com.br/blog/blog/os-dados-que-a-maioria-das-pessoas-usa-para-treinar-seus-modelos-de-inteligencia-artificial- ja-vem-com-um-vies-embutido/..

    Сильный ИИ против слабого ИИ: различия парадигм искусственного интеллекта
    В последние годы изучению и развитию искусственного интеллекта (ИИ) уделяется большое внимание и прогресс. Сильный ИИ и Слабый ИИ — две основные парадигмы в области искусственного интеллекта...

    Правильный способ добавить Firebase в ваш проект React с помощью React Hooks
    React + Firebase - это мощная комбинация для быстрого и безопасного создания приложений, от проверки концепции до массового производства. Раньше (знаете, несколько месяцев назад) добавление..

    Создайте API с помощью Python FastAPI
    Создание API с помощью Python становится очень простым при использовании пакета FastAPI. После установки и импорта вы можете создать приложение FastAPI и указать несколько конечных точек. Каждой..

    Веселье с прокси-сервером JavaScript
    Прокси-серверы JavaScript — это чистый сахар, если вы хотите создать некоторую общую логику в своих приложениях, чтобы облегчить себе жизнь. Вот один пример: Связь клиент-сервер Мы..

    Получить бесплатный хостинг для разработчиков | Разместите свой сайт за несколько шагов 🔥
    Статические веб-сайты — это веб-страницы с фиксированным содержанием и его постоянным содержанием. Но теперь статические сайты также обрабатывают динамические данные с помощью API и запросов...