Код как:
public Thing[] getThings(){
return things;
}
Не имеет особого смысла, так как ваш метод доступа не делает ничего, кроме непосредственного возврата внутренней структуры данных. С тем же успехом вы можете просто заявить Thing[] things
о себе public
. Идея метода доступа состоит в том, чтобы создать интерфейс, который изолирует клиентов от внутренних изменений и не позволяет им манипулировать реальной структурой данных, за исключением скрытых способов, разрешенных интерфейсом. Как вы обнаружили, когда весь ваш клиентский код сломался, ваш метод доступа этого не сделал - это просто напрасный код. Я думаю, что многие программисты, как правило, пишут такой код, потому что они где-то узнали, что все должно быть инкапсулировано с методами доступа - но это по причинам, которые я объяснил. Делать это просто для того, чтобы «следовать форме», когда метод доступа не служит какой-либо цели, - это просто шум.
Я определенно рекомендую ваше предлагаемое решение, которое решает некоторые из наиболее важных задач инкапсуляции: предоставление клиентам надежного, незаметного интерфейса, который изолирует их от внутренних деталей реализации вашего класса и не позволяет им касаться внутренней структуры данных. ожидайте способами, которые вы решите, уместны - «закон наименее необходимой привилегии». Если вы посмотрите на большие популярные платформы ООП, такие как CLR, STL, VCL, предложенный вами шаблон широко распространен именно по этой причине.
Вы должны всегда делать это? Не обязательно. Например, если у вас есть вспомогательные или дружественные классы, которые, по сути, являются компонентом вашего основного рабочего класса и не являются «фронтальными», это необязательно - это излишнее количество, которое добавит много ненужного кода. И в этом случае я бы вообще не использовал метод доступа - как объяснено, это бессмысленно. Просто объявите структуру данных так, чтобы она была доступна только для основного класса, который ее использует - большинство языков поддерживают способы сделать это - friend
или объявив ее в том же файле, что и основной рабочий класс, и т. Д.
Единственный недостаток, который я вижу в вашем предложении, заключается в том, что это больше работы для кодирования (и теперь вам придется перекодировать ваши потребительские классы - но вы все равно должны были это делать). Но это не совсем недостаток - Вы должны сделать это правильно, а иногда это требует больше работы.
Одна из вещей, которая делает хорошего программиста хорошим, заключается в том, что они знают, когда дополнительная работа того стоит, а когда - нет. В конечном счете, добавление дополнительного сейчас окупится большими дивидендами в будущем - если не на этом проекте, то на других. Научитесь правильно кодировать и использовать свою голову, а не просто роботизированно следовать предписанным формам.
Обратите внимание, что коллекции, более сложные, чем массивы, могут требовать, чтобы вмещающий класс реализовал даже более трех методов только для доступа к внутренней структуре данных.
Если вы представляете всю структуру данных через содержащий класс, IMO, вам нужно подумать о том, почему этот класс вообще инкапсулирован, если не просто предоставить более безопасный интерфейс - «класс-обертку». Вы говорите, что содержащий класс не существует для этой цели - так что, возможно, что-то не так с вашим дизайном. Подумайте о том, чтобы разбить ваши классы на более дискретные модули и разбить их на слои.
Класс должен иметь одну ясную и незаметную цель и предоставлять интерфейс для поддержки этой функциональности - не более. Возможно, вы пытаетесь связать вещи, которые не принадлежат друг другу. Когда вы это сделаете, вещи будут ломаться каждый раз, когда вам нужно будет внести изменения. Чем меньше и деликатнее ваши занятия, тем легче изменить положение вещей: подумайте LEGO.
get(index)
,add()
,size()
,remove(index)
, иremove(Object)
. Используя предложенную технику, класс, который содержит этот ArrayList, должен иметь пять открытых методов только для делегирования внутренней коллекции. И цель этого класса в программе, скорее всего, заключается не в инкапсуляции этого ArrayList, а скорее в выполнении чего-то другого. ArrayList - это просто деталь. [...]