Это нормально для интерфейсов, чтобы зависеть от конкретных классов?


9

Я создаю интерфейс на Java для пользовательского обработчика ошибок.

Хочу передать объект ошибки аргумента, но мне нужно, чтобы он был потомком Exceptionкласса.

Можно ли использовать мое имя класса в интерфейсе?

Разве это не сделает его менее интерфейсным с точки зрения отсутствия зависимости от какой-либо реализации?

Я пытаюсь сделать что-то вроде этого:

public class CustomException {
    /* ... Implementation ... */
}

public interface Interface {

    void onError(CustomException ex);

}

Вы пытаетесь спросить, нормально ли наследовать другой класс в интерфейсе?
Снуп

@ StevieV Нет. Я редактировал вопрос, смотри.
nikachx

1
@AndresF. Это всего лишь пример, и его можно применять к любому языку OO об использовании классов в интерфейсах.
nikachx

3
Подскажите: это CustomExceptionчасть реализации или часть интерфейса?
user253751

2
@nikachx Я не понимаю, что вы подразумеваете под "безопасным". Чем Stringбезопаснее CustomException? Почему это важно, если CustomException, в свою очередь, имеет другие зависимости?
Андрес Ф.

Ответы:


2

Во-первых, я должен указать на тот факт, что CustomExceptionэто не распространяется, Exceptionпоэтому это не совсем так Exception.

Это говорит:

Если вам не важен принцип инверсии зависимости , оставьте его как есть. Это совершенно нормально для интерфейса , чтобы зависеть от классов конкретных, например , многие интерфейсы зависят от Stringили Objectкоторые являются конкретными классами . Дело в том, что мы склонны полагать, что классы, принадлежащие Java SDK, более стабильны (менее подвержены изменениям, нарушающим код), чем те, которые мы пишем.

С другой стороны:

Если вы хотите следовать DIP (который имеет бесчисленные преимущества и является моей рекомендацией), то вы должны сделать одну из двух вещей:

Опция 1

  • Сделать CustomExceptionаннотацию
  • Держи void onError(CustomException ex)как есть

Вариант 2

  • Сделать CustomExceptionинтерфейс
  • Держи void onError(CustomException ex)как есть

С любой из этих опций вы будете соответствовать DIP, так как интерфейс не будет зависеть от какого-либо конкретного класса, только от абстракций.

При непосредственном применении инверсии зависимостей рефераты принадлежат верхним уровням / уровням политики. Эта архитектура группирует компоненты верхнего уровня / политики и рефераты, которые определяют низшие сервисы вместе в одном пакете. Уровни более низкого уровня создаются путем наследования / реализации этих абстрактных классов или интерфейсов . Мартин, Роберт С. (2003).

  • Agile Software Development, Принципы,> Шаблоны и Практики. Прентис Холл. С. 127–131. ISBN 978-0135974445.

1
Нет большой разницы между принятием абстрактного класса или конкретного (не финального) класса, и разница с интерфейсом не намного больше чем это. Пока экземпляр передается в качестве параметра и не жестко задан в вашей реализации, у вас есть основания для DI.
Джейкоб Райле

@JacobRaihle Что вы имеете в виду, передавая экземпляр, жестко закодированный в реализации?
Тулаинс Кордова

Я сказал «пока это передано и не жестко закодировано». Я имею в виду, что поскольку Interfaceинтерфейс принимает a CustomExceptionи оставляет его вызывающей стороне для его предоставления, вызывающая сторона может предоставить любой класс, который расширяется, CustomExceptionдаже если CustomExceptionэто конкретный класс - что было бы невозможно, если бы Interfaceон каким-то образом отвечал за создание Это. Эта инверсия управления, более чем работа с интерфейсами (хотя это, безусловно, помогает), это то, чем я считаю DI.
Джейкоб Райле

@JacobRaihle "При прямом применении инверсии зависимостей, рефераты принадлежат верхним уровням / политикам. Эта архитектура группирует компоненты высшего уровня / политики и тезисы, которые определяют низшие сервисы вместе в одном пакете. Создаются слои нижнего уровня. наследованием / реализацией этих абстрактных классов или интерфейсов . " Мартин, Роберт С. (2003). Гибкая разработка программного обеспечения, принципы, шаблоны и практики. Прентис Холл. С. 127–131. ISBN 978-0135974445.
Тулаинс Кордова

Какой смысл в абстрактном классе, если вы можете предоставить разумное значение по умолчанию? Что вы теряете , предоставляя это? Не просто цитируйте книги, думайте.
Джейкоб Райле

2

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

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


0

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

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

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


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

2
Ответы, которые задают вопросы ОП ... Просто спросите в комментарии, затем предоставьте свой ответ.
Снуп

1
@ StevieV: Первый абзац был скорее риторическим вопросом. И, как видно из комментария ФП, я фактически ответил на вопрос ФП.
Арсений Мурзенко
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.