Чи правильно інтерфейси залежати від конкретних класів?


9

Я створюю в Java інтерфейс для користувальницького обробника помилок.

Хочете передати об’єкт помилки аргументу, але мені потрібно, щоб він був дочірнім Exceptionкласом.

Чи добре використовувати моє визначене ім’я класу в інтерфейсі?

Чи не зробить це менш інтерфейсом з точки зору того, що він не залежить від будь-якої реалізації?

Я намагаюся зробити щось подібне:

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

public interface Interface {

    void onError(CustomException ex);

}

Ви намагаєтеся запитати, чи добре наслідувати інший клас в інтерфейсі?
Snoop

@StevieV Ні. Я редагував питання, дивіться.
nikachx

1
@AndresF. Це лише приклад і може бути застосований до будь-якої мови ОО щодо використання класів в інтерфейсах.
nikachx

3
Скажіть мені: це CustomExceptionчастина реалізації чи частина інтерфейсу?
користувач253751

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 Розробка програмного забезпечення, Принципи,> Шаблони та практики. Prentice Hall. С. 127–131. ISBN 978-0135974445.

1
Існує не велика різниця між прийняттям абстрактного класу або конкретного (не остаточного) класу, і різниця в інтерфейсі не набагато більша. Поки екземпляр передається як параметр і не жорстко закодований у вашій реалізації, у вас є основи для DI.
Яків Райхле

@JacobRaihle Що ви маєте на увазі, передаючи екземпляр, жорстко закодований у реалізації?
Тулен Кордова

Я сказав "до тих пір, поки пройде і не буде жорстко закодовано". Я маю на увазі те, що оскільки Interfaceінтерфейс приймає a CustomExceptionі залишає його для абонента, щоб надати його, абонент може надати будь-який клас, який розширюється, CustomExceptionнавіть якщо CustomExceptionце конкретний клас - що не було б можливим, якби Interfaceякимось чином відповідав за створення це. Я думаю, що це все інше.
Яків Райхле

@JacobRaihle "При прямому застосуванні інверсії залежностей тези доповідей належать верхнім / шарам політики. Ця архітектура групує вищі компоненти / політики та конспекти, які визначають нижні служби разом у одному пакеті. Низькі рівні створюються шляхом успадкування / реалізації цих абстрактних класів або інтерфейсів . " Мартін, Роберт К. (2003). Agile Розробка програмного забезпечення, принципи, шаблони та практики. Prentice Hall. С. 127–131. ISBN 978-0135974445.
Tulains Córdova

Який сенс абстрактного класу, якщо ви можете надати розумний дефолт? Що ви втрачаєте , надаючи це? Не просто цитуйте книги, подумайте.
Яків Райхле

2

Tulains правильно - інтерфейси весь час залежать від конкретних класів. Вони призначені лише для створення договору для власних проблем. Цей договір може передбачати отримання та повернення будь-яких даних.

Пам’ятайте, що в мовах вищого рівня навіть примітивні типи не такі примітивні. Тож ви все одно працюєте з бетонними типами!


0

Я гадаю, назвою ви маєте на увазі сам власне клас. Якщо ви намагаєтеся вказати фактичне ім'я класу винятку для ініціалізації відповідного винятку через Reflection, це не правильний шлях.

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

Якщо вам потрібно використовувати різні винятки залежно від контексту, то, можливо, вам буде цікаво використовувати generics.


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

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

1
@StevieV: Перший абзац був скоріше риторичним питанням. І як показано в коментарі ОП, я фактично відповів на питання ОП.
Арсеній Муренко
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.