Коротка відповідь: безпечно, якщо ви їх безпечно використовуєте :)
Спритна відповідь: скажіть, що ви маєте на увазі під рисами, і, можливо, я дам вам кращу відповідь :)
По суті, термін "риса" недостатньо визначений. Багато розробників Java найбільше знайомі з ознаками, оскільки вони виражаються в Scala, але Scala далеко не перша мова, яка має риси як за назвою, так і за дією.
Наприклад, у Scala ознаки є стаціонарними (можуть мати var
змінні); у фортеці вони є чистою поведінкою. Інтерфейси Java з методами за замовчуванням без стану; це означає, що вони не риси? (Підказка: це було хитрі питання.)
Знову ж таки, у Scala риси складаються за допомогою лінеаризації; якщо клас A
розширює ознаки X
і Y
, то порядок, в якому X
і Y
змішуються, визначає, як конфлікти між X
і Y
вирішуються У Java цього механізму лінеаризації немає (частково його було відхилено, оскільки він був надто "не схожий на Java".)
Найближчою причиною додавання методів за замовчуванням до інтерфейсів було підтримка еволюції інтерфейсу , але ми добре розуміли, що ми виходили за рамки цього. Чи вважаєте ви, що це "еволюція інтерфейсу ++" чи "риси - це питання особистого тлумачення". Отже, щоб відповісти на ваше запитання щодо безпеки ... поки ви будете дотримуватися того, що механізм насправді підтримує, а не намагатися бажано розтягнути його на щось, що він не підтримує, вам слід добре.
Основна мета дизайну полягала в тому, щоб, з точки зору клієнта інтерфейсу, методи за замовчуванням не відрізнялися від "звичайних" методів інтерфейсу. Отже, стандартність методу цікава лише дизайнеру та реалізатору інтерфейсу.
Ось кілька випадків використання, які добре входять у цілі дизайну:
Еволюція інтерфейсу. Тут ми додаємо новий метод до вже існуючого інтерфейсу, який має розумну реалізацію за замовчуванням щодо існуючих методів цього інтерфейсу. Прикладом може бути додавання forEach
методу до Collection
, де реалізація за замовчуванням написана з точки зору iterator()
методу.
"Необов'язкові" методи. Тут дизайнер інтерфейсу говорить: "Інвесторам не потрібно застосовувати цей метод, якщо вони готові жити з обмеженнями у функціональності, що тягне за собою". Наприклад, Iterator.remove
був заданий за замовчуванням, який кидає UnsupportedOperationException
; оскільки переважна більшість реалізацій Iterator
має таку поведінку, то за замовчуванням цей метод по суті є необов'язковим. (Якщо поведінка з AbstractCollection
висловлюється як за замовчуванням Collection
, ми могли б зробити те ж саме для мутативних методів.)
Зручні методи. Це методи, які суворо для зручності, знову ж таки загально реалізовані з точки зору методів, що не застосовуються за замовчуванням у класі. logger()
Метод в першому прикладі є розумною ілюстрацією.
Комбінатори. Це композиційні методи, які створюють нові екземпляри інтерфейсу на основі поточного екземпляра. Наприклад, методи Predicate.and()
або Comparator.thenComparing()
є прикладами комбінаторів.
Якщо ви надаєте реалізацію за замовчуванням, ви також повинні надати певну специфікацію для замовчування (у JDK ми використовуємо @implSpec
тег javadoc для цього), щоб допомогти інженерам зрозуміти, хочуть вони замінити метод чи ні. Деякі параметри за замовчуванням, як-от зручні методи та комбінатори, майже ніколи не змінюються; інші, як необов'язкові методи, часто перекриваються. Потрібно надати достатню специфікацію (не лише документацію) про те, що обіцяє зробити за замовчуванням, щоб виконавець міг прийняти обґрунтоване рішення про те, чи потрібно їм це перекривати.