Класс Java, содержащий только закрытые члены

Недавно я столкнулся с ситуацией, когда мне нужно было создать собственный VideoView в мое приложение для Android. Мне нужен был доступ к объекту MediaPlayer и добавить слушателей.

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

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


person MByD    schedule 24.04.2011    source источник


Ответы (4)


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

person Tom Anderson    schedule 24.04.2011
comment
+1 См. также Bloch. Пункт 16: Предпочтите композицию наследованию и Пункт 17: Разработайте и задокументируйте наследование или же запретите ему разрабатывать этот сложный компромисс. - person trashgod; 25.04.2011

Обычно в таких ситуациях я предпочитаю композицию наследованию.

EDIT:
Использование наследования безопасно, когда и подкласс, и суперкласс находятся под контролем одного и того же программиста, но наследование реализации может привести к нестабильности API. Как вы упомянули, если реализация суперкласса изменится, подкласс может сломаться или, что еще хуже, будет делать непреднамеренные вещи молча.

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

person Premraj    schedule 24.04.2011
comment
См. также Разговор с Эрихом Гаммой, часть III - person trashgod; 24.04.2011
comment
@ Сокол - это то, что я думал, ты имел в виду. В данном случае эта схема для меня неактуальна. - person MByD; 25.04.2011
comment
@trashgod - мне очень понравилась ссылка, которую вы разместили - person MByD; 25.04.2011
comment
@MByD - я чувствую, что это или какой-то вариант этого вам следует поискать .. а насчет VideoView - я чувствую, что они поступили правильно :) - person Premraj; 25.04.2011

Я не могу говорить о рассуждениях конкретных разработчиков VideoView, но если вы разрабатываете API и определяете, что состояние, представленное определенными данными, должно всегда следовать определенным правилам, чтобы поддерживать целостность и предполагаемое назначение объекта, то имеет смысл сделать переменные-члены закрытыми, чтобы вы могли контролировать их модификацию.

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

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

person roberttdev    schedule 24.04.2011
comment
поскольку я согласен с тем, что вы говорите, я думаю, что, проектируя такой класс, вы полностью теряете возможность наследовать от него, что является одной из основных концепций ООП, и не просто так. Если я внесу изменения в подкласс, которые нарушают целостность класса, это моя ответственность, и это касается только меня/моих клиентов. - person MByD; 24.04.2011
comment
@MByD — если вы пишете API, вы можете создать класс для наследования, например — SurfaceView , который можно расширить, но VideovView — это реализация виджета, поэтому хорошо защищать переменные, чтобы сохранить поведение нетронутым ... для конечных пользователей, таких как Мы можем ожидать создания реализации SurfaceView. - person Premraj; 24.04.2011
comment
Вы определенно делаете (хотя вы можете несколько смягчить это, предоставив тщательные методы доступа). Но на самом деле все зависит от людей, чья работа заключается в управлении кодом. Они принимают решение, что есть что-то, с чем они не хотят, чтобы другие разработчики под ними (или использующие их API) связывались без их одобрения. - person roberttdev; 24.04.2011
comment
Еще одна вещь, на которую следует обратить внимание, это то, что в таких проектах с открытым исходным кодом они, вероятно, хотят, чтобы обычный человек, проверяющий обновления API, не связывался с этим. Если он настроен таким образом, только архитекторы с высшим доступом могут принять решение об его изменении. Таким образом, проверки не могут испортить работу для всех, кто использует API. - person roberttdev; 24.04.2011

Когда я прочитал все поучительные ответы (и комментарии) и комментарии к ним, я понял, что ожидал чего-то неуместного от некоторых классов. В случае примера VideoView fr этот класс уже является последним в цепочке наследования. Его не следует расширять, так как это одна логическая единица, очень конкретная и очень тесная, для очень конкретной цели. Мои потребности, чтобы получить специальные состояния из представления и MediaPlayer, были необходимы для целей контроля качества, и такие потребности действительно не следует учитывать при предоставлении продукта, который является закрытым блоком (хотя исходный код открыт). Это разумный аргумент, и я нахожу его удовлетворительным. Иногда не следует реализовывать каждую концепцию ООП. Спасибо всем за ответы.

person MByD    schedule 24.04.2011
comment
+1 Думаю, вам понравится глава 4 книги Bloch. - person trashgod; 25.04.2011