Достоинства геттеров и сеттеров
- Используя геттеры и сеттеры вы можете осуществлять контроль за тем, какие именно данные содержатся в свойствах объекта, и отклонять любые некорректные значения.
- Так же вы можете осуществлять дополнительные операции перед тем, как установить или получить значение свойства (например, если обновление данного свойства должно вызывать некоторое действие, такое как оповещение пользователя).
- При установке значения, которое является объектом или массивом, вы можете явно указать тип переменной в сигнатуре функции(прим. public function setBar(Bar $bar)). К большому сожалению, PHP не позволяет проделывать тоже самое с типами int и string!
- Если значение свойства должно получаться из внешнего источника или среды исполнения, вы можете использовать ленивую загрузку данных — таким образом ресурсы, требуемые для загрузки данных, будут задействованы непосредственно во время получения значения свойства. Разумеется, в данном случае нужно соблюдать осторожность, и не следует получать данные из внешнего источника при каждом обращении к свойству. Будет лучше сделать одно обращение к базе данных и заполнить значения всех свойств сразу, чем делать это для каждого в отдельности.
- Вы можете сделать свойство доступным только на чтение или только на запись, путём создания только геттера или только сеттера.
- Вы можете добавить геттеры и сеттеры в интерфейс для того, чтобы отобразить их в API.
Недостатки геттеров и сеттеров
- Для разработчиков, которые используют прямой доступ к свойствам, геттеры и сеттеры кажутся настоящей головной болью! Для каждого свойства нужно определить само свойство, геттер и сеттер; и для того чтобы использовать данное свойство в коде, нужно осуществлять дополнительные вызовы метода — намного легче написать $foo->bar++; вместо $foo->setBar($foo->getBar() + 1); (хотя, конечно, можно добавить ещё один метод $foo->incrementBar();)
- Как уже отмечалось выше, существуют небольшие дополнительные расходы, затрачиваемые на вызов метода.
- Имена геттеров и сеттеров принято начинать с глаголов get и set, но данные глаголы так же могут использоваться и в других методах, которые ни коим образом не относятся к свойствам класса.
<fieldset>
<legend>СЛОВО</legend>
Текст Текст Текст Текст Текст Текст Текст Текст Текст
Текст Текст Текст Текст Текст Текст Текст Текст Текст
Текст Текст Текст Текст Текст Текст Текст Текст Текст
Текст Текст Текст Текст Текст Текст Текст Текст Текст
Текст Текст Текст Текст Текст Текст Текст Текст Текст
Текст Текст Текст Текст Текст Текст Текст Текст Текст
</fieldset>
# строим всевозможные комбинации кирпичей длинной 25
nxt, rows = [(3,), (4,)], []
while nxt:
cur, nxt = nxt, []
for row in cur:
for brick in 3, 4:
le = row[-1] + brick
if le < 23:
nxt.append(row + (le,))
elif le == 25:
rows.append(frozenset(row))
# все комбинации длинны 25 лежат в листе rows, т.е. занумерованы
# строим лист, где по номеру каждой комбинации
# лежит список номеров неконфликтующих комбинаций
friendly_row = [[i for i, b in enumerate(rows) if not (a & b)] for a in rows]
nxt = [1] * len(rows) # в первом слое может лежать любая комбинация
for _ in range(10 - 1): # есть же один слой
cur, nxt = nxt, [0] * len(rows)
for i, n in enumerate(cur):
for j in friendly_row[i]:
nxt[j] += n
print(sum(nxt))
cache = {}
def build_tail(height, row):
if height == 9:
return neighbours_number[row]
if (height, row) in cache:
return cache[height, row]
cache[height, row] = res = sum(build_tail(height + 1, i) for i in acceptable_neighbours[row])
return res
rows = {i for i in itertools.permutations([3, 3, 3, 4, 4, 4, 4], 7)} | \
{i for i in itertools.permutations([3, 3, 3, 3, 3, 3, 3, 4], 8)}
acc_rows = [set(itertools.accumulate(row[: -1])) for row in rows]
acceptable_neighbours = [[i for i, b in enumerate(acc_rows) if not (a & b)] for a in acc_rows]
neighbours_number = [len(i) for i in acceptable_neighbours]
print(sum(build_tail(1, i) for i in range(0, len(acc_rows))))