Java-класс, содержащий только закрытые члены
В последнее время я столкнулся с ситуацией, когда мне нужно было создать собственный VideoView для моего приложения для Android. Мне нужен был доступ к объекту MediaPlayer и добавить несколько слушателей.
К сожалению (для меня), все члены класса VideoView являются частными, поэтому даже расширение класса не помогло бы мне получить доступ к его объекту MediaPlayer (или чему-либо еще), мне пришлось сделать полную копию класса с моим модификаций.
Ну, хотя это звучит так, будто я жалуюсь на "тяжелую работу", это проще, чем расширение класса в этом случае (поскольку весь источник доступен...), но это заставило меня действительно усомниться в этом методе информации прячется. Является ли это лучшей практикой, чем оставлять основные компоненты доступными для модификации / доступа (защищенными, а не общедоступными)? Я имею в виду, что я понимаю, что если я расширю класс VideoView, возможно, когда-нибудь они что-то изменят в классе VideoView, и у меня могут возникнуть проблемы, но если они изменят класс, моя собственная (дублированная) версия будет иметь большую разницу из класса VideoView, и моя цель не состоит в том, чтобы создать свой собственный просмотр видео, но расширить доступный VideoView.
4 ответа
Когда программист делает что-то личное, он делает ставку на то, что больше никто не будет нуждаться в том, чтобы использовать или переопределить это, и поэтому от сокрытия информации будет выигрыш. Иногда эта ставка не снимается. Это перерывы.
Я обычно предпочитаю композицию, а не наследование в таких ситуациях.
РЕДАКТИРОВАТЬ:
Безопасно использовать наследование, когда подкласс и суперкласс находятся под управлением одного и того же программиста, но наследование реализации может привести к хрупкому API. Как вы упомянули, если реализация суперкласса изменится, то подкласс может сломаться или, что еще хуже, будет совершать непреднамеренные действия молча
Другой подход заключается в том, чтобы иметь закрытое поле, которое ссылается на экземпляр существующего класса (VideoView), известный как состав, и каждый метод экземпляра в новом классе вызывает соответствующий метод для содержащегося экземпляра существующего класса и возвращает результаты. Этот подход обертки можно также назвать шаблоном "Декоратор"
Когда я прочитал все поучительные ответы (и комментарии) и комментировал их, я понял, что ожидал чего-то, что не имеет отношения к некоторым занятиям. В случае с VideoView fr этот класс уже является последним в цепочке наследования. Его не следует расширять, поскольку это одна логическая единица, очень конкретная и очень узкая, для очень конкретной цели. Мои потребности, чтобы получить особые состояния от представления и MediaPlayer, были потребностями для целей контроля качества, и такие потребности действительно не должны учитываться при предоставлении продукта, который является закрытым модулем (хотя источник является открытым). Это разумный аргумент, и я нахожу его удовлетворительным. Иногда не каждая концепция ООП должна быть реализована. Спасибо всем за ответы.
Я не могу говорить по соображениям конкретных разработчиков VideoView, но если вы разрабатываете API и определяете, что состояние, представленное определенными данными, должно всегда следовать определенным правилам, чтобы поддерживать целостность и предполагаемое назначение объекта, тогда имеет смысл сделать член vars закрытым, чтобы вы могли контролировать их модификацию.
Это действительно ограничивает то, что могут сделать другие разработчики, но я предполагаю, что в этом суть. Есть некоторые вещи, которые, если бы их нужно было изменить, вы бы хотели, чтобы они прошли обсуждение и проверку в группе, которая управляет API. В этом случае имеет смысл провести приватизацию, чтобы ее изменения не вышли из-под контроля группы.
Я не знаю, что есть эмпирическое правило, которое определяет, когда что-то должно попадать в эту категорию, но я определенно вижу применение в некоторых случаях.