Первый метод довольно стандартный. Он четко определяет свойства и позволяет IDE и инструментам документирования кода выбирать доступные свойства объекта.
Второй метод отлично подходит для свойств защищенного и частного уровня, в которых необходимо хранить данные в отдельной области видимости. Я использую комбинацию обоих подходов в различных классах моделей или для отслеживания параметров конфигурации и значений по умолчанию. Однако я всегда буду предварительно заполнять эти массивы и обеспечивать строгое соблюдение данных внутри.
Я бы никогда не рекомендовал использовать второй метод для публичного свойства, поскольку он демонстрирует отсутствие понимания свойств объекта и области видимости переменных и может привести к проблемам в коде (что, если кто-то перезапишет этот корневой массив строкой? )
Использование методов получения и установки позволяет использовать свойства, которые необходимо изменить в вызывающем коде. Не каждое свойство должно быть доступным, так что это зависит от разработчика, определяющего объект. Шаблон getter / setter не имеет смысла для общедоступных свойств, очевидно, но он имеет значение для защищенных и приватных свойств, которые могут нуждаться в некоторой проверке или быть очищенными. Они также имеют смысл в контексте внедрения зависимостей.