Привет, Дзен!
Поговорим о парадоксе Брадобрея:
Пусть в некой деревне живёт брадобрей, который бреет всех жителей деревни, которые не бреются сами, и только их.
Бреет ли брадобрей сам себя?
Это одна из формулировок парадокса Рассела.
С точки зрения математики — ничего нового. Брадобрей не может ни брить, ни не брить себя. Похоже, его просто не существует.
Но в реальной жизни мы не имеем дело с бесконечностями, множествами всех множеств и прочими чудесами. Предлагаю посмотреть на Брадобрея с практической точки зрения.
Как Брадобрей узнает, кто бреется, а кто нет?
Брадобрей — человек
Итак, представим себе молодого человека, который после школы окончил курсы брадобреев. Вот, он с утра обходит каждый дом в поисках мужчин, которые не бреются. Не бреются или не побрились? Это важный момент. Формулировка парадокса ближе к "не бреются", но мы рассмотрим разные варианты.
Список
"Не бреются" — это некоторое состояние человека. В этом случае у Брадобрея есть список тех, кто не бреется и кого надо брить. Как составлялся этот список? Предположим, Брадобрей в первый раз обошел всех жителей и спросил: "вас брить по утрам?". Потом он вернулся домой и задумался, вносить ли себя в этот список. Если молодой брадобрей интересовался математикой в школе и, не дай Бог, читал начала теории множеств, то на этом месте он должен зависнуть и умереть с голоду. В противном случае он без труда решит эту проблему. Зачем в свой список вносить себя? Все просто — встал, побрился, пошел брить других.
Вопрос
Брадобрей задает прямой вопрос: "ты бреешься сам?". Психически здоровый человек долго разговаривать с собой не станет и быстро справится с таким вопросом.
Самостоятельное принятие решения
Брадобрей пытается узнать, нужно ли брить человека, оценивая его самостоятельно. С визуальной оценкой все просто. Смотрим на человека, видим щетину, понимаем, что нужно брить. С собой — то же самое только через зеркало. Отросла борода — сбриваешь. Все просто.
Понятно, что в случае с человеком парадоксов не возникает, а что если брадобрей — это робот или программа?
Брадобрей — программа
В этом случае важно как написан код такой программы. Создадим класс для обычного жителя:
Создаем деревню:
С утра в деревне будет происходить нечто такое:
Теперь посмотрим, как может быть устроен Barber:
Проверяем, бреется ли человек сам по флагу isSelfShave. Если да, вызываем метод selfShave(), если нет — сбриваем бороду сами. Что в этом случае барбер сделает сам с собой? Ничего страшного не произойдет. Если isSelfShave = true, то сработает selfShave() унаследованный от Human, если isSelfShave = false, то барбер побреет себя методом shaveHuman().
В условии вместо isSelfShave можно проверять beard, что соответствует самостоятельному принятию решения. В этом случае также не возникает никаких проблем.
Как же нам воспроизвести парадокс? Вообще говоря, надо сильно потрудиться, чтобы попасть в рекурсию.
Например так:
Переопределяем метод selfShave() для барбера. Тогда, если isSelfShave = true, метод shaveHuman() вызовет selfShave(). В этот момент барбер подумает, что он бреется сам, но при этом его бреет барбер, а барбер не бреет тех, кто бреется сам. Не в состоянии принять какое-то решение, метод selfShave() передаст право выбора shaveHuman() и все повторится заново. Надо сказать, что даже такая логика не совсем соответствует логике парадокса. Кроме того, ни один программист в здравом уме не напишет такой метод selfShave в Barber.
Получается, то, что в математике парадокс, в программировании просто плохой код!