Как объяснить концепции объектно-ориентированного программирования 6-летнему ребенку

Вы замечали, как одни и те же клише вопросы всегда задаются на собеседовании - снова и снова?

Я уверен, вы понимаете, о чем я.

Например:

Каким вы видите себя через пять лет?

или, что еще хуже:

Что вы считаете своей самой большой слабостью?

Ух ... дай мне передохнуть. Считаю ответ на этот вопрос большой слабостью! Во всяком случае, я не о том.

Какими бы тривиальными ни были подобные вопросы, они важны, потому что они дают подсказку о вас. Ваше текущее состояние ума, ваше отношение, ваша точка зрения.

При ответе будьте осторожны, так как вы можете рассказать о чем-то, о чем позже пожалеете.

Сегодня я хочу поговорить о подобном типе вопросов в мире программирования:

Каковы основные принципы объектно-ориентированного программирования?

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

Обычно на него приходится отвечать младшим и начинающим разработчикам. Потому что интервьюер может легко сказать три вещи:

  1. Кандидат готовился к этому собеседованию?

    Бонусные баллы, если вы сразу услышите ответ - это серьезный подход.

  2. Кандидат прошел этап обучения?

    Понимание принципов объектно-ориентированного программирования (ООП) показывает, что вы вышли за рамки копирования и вставки из руководств - вы уже видите вещи с более высокой точки зрения.

  3. Понимание кандидата глубокое или поверхностное?

    Уровень компетентности по этому вопросу часто равен уровню компетентности по большинству других предметов . Доверьтесь мне.

Четыре принципа объектно-ориентированного программирования: инкапсуляция , абстракция , наследование ,и полиморфизм .

Эти слова могут показаться пугающими для начинающего разработчика. А сложные, чрезмерно длинные объяснения в Википедии иногда удваивают путаницу.

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

Инкапсуляция

Допустим, у нас есть программа. В нем есть несколько логически разных объектов, которые взаимодействуют друг с другом в соответствии с правилами, определенными в программе.

Инкапсуляция достигается, когда каждый объект сохраняет свое частное состояние внутри класса. Другие объекты не имеют прямого доступа к этому состоянию. Вместо этого они могут вызывать только список общедоступных функций, называемых методами.

Таким образом, объект управляет своим собственным состоянием с помощью методов - и никакой другой класс не может коснуться его, если явно не разрешено. Если вы хотите общаться с объектом, вы должны использовать предоставленные методы. Но (по умолчанию) вы не можете изменить состояние.

Допустим, мы создаем крошечную игру Sims. Есть люди и есть кошка. Они общаются друг с другом. Мы хотим применить инкапсуляцию, поэтому мы инкапсулируем всю «кошачью» логику вCatкласс. Это может выглядеть так:

Здесь «состояние» кота - это частные переменныеmood , hungryи energy. У него также есть частный метод meow(). Он может вызывать его, когда захочет, другие классы не могут сказать кошке, когда нужно мяукать.

Что они могут сделать , это определить в общих методахsleep() , play()и feed(). Каждый из них каким-то образом изменяет внутреннее состояние и может вызывать meow(). Таким образом, выполняется привязка между частным состоянием и общедоступными методами.

Это инкапсуляция.

Абстракция

Абстракцию можно рассматривать как естественное расширение инкапсуляции.

В объектно-ориентированном дизайне программы часто бывают очень большими. А отдельные объекты много общаются друг с другом. Так что поддерживать такую ​​большую кодовую базу в течение многих лет - с постоянными изменениями - сложно.

Абстракция - это концепция, призванная облегчить эту проблему.

Применение абстракции означает, что каждый объект должен предоставлять только высокоуровневый механизм для его использования.

Этот механизм должен скрывать детали внутренней реализации. Он должен раскрывать только операции, относящиеся к другим объектам.

Думаю - кофеварка. Он делает много вещей и издает странные звуки под капотом. Но все, что вам нужно сделать, это налить кофе и нажать кнопку.

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

Еще один пример абстракции из реальной жизни?

Подумайте, как вы используете свой телефон:

Вы взаимодействуете со своим телефоном, используя всего несколько кнопок. Что творится под капотом? Вам не обязательно знать - детали реализации скрыты. Вам нужно знать лишь небольшой набор действий.

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

Наследование

Хорошо, мы увидели, как инкапсуляция и абстракция могут помочь нам разработать и поддерживать большую кодовую базу.

Но знаете ли вы, какова еще одна распространенная проблема в дизайне ООП?

Объекты часто очень похожи. У них общая логика. Но они не совсем то же самое. Ух ...

Так как же нам повторно использовать общую логику и выделить уникальную логику в отдельный класс? Один из способов добиться этого - наследование.

Это означает, что вы создаете (дочерний) класс, производя его от другого (родительского) класса. Таким образом, мы формируем иерархию.

Дочерний класс повторно использует все поля и методы родительского класса (общая часть) и может реализовать свою собственную (уникальную часть).

Например:

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

Таким образом, каждый класс добавляет только то, что ему необходимо, при повторном использовании общей логики с родительскими классами.

Полиморфизм

Мы подошли к самому сложному слову! Полиморфизм в переводе с греческого означает «множество форм».

Итак, мы уже знаем силу наследования и с радостью ею пользуемся. Но возникает такая проблема.

Скажем, у нас есть родительский класс и несколько дочерних классов, которые наследуются от него. Иногда мы хотим использовать коллекцию, например список, которая содержит смесь всех этих классов. Или у нас есть метод, реализованный для родительского класса, но мы хотели бы использовать его и для детей.

Это можно решить с помощью полиморфизма.

Проще говоря, полиморфизм дает возможность использовать класс точно так же, как его родительский, поэтому нет путаницы со смешением типов.Но каждый дочерний класс сохраняет свои собственные методы как есть.

Обычно это происходит путем определения (родительского) интерфейса для повторного использования. В нем описывается ряд общих методов. Затем каждый дочерний класс реализует свою собственную версию этих методов.

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

Взгляните на эскиз реализации геометрических фигур. Они повторно используют общий интерфейс для расчета площади поверхности и периметра:

Имея эти три цифры наследуя родителей Figure Interfaceпозволяет создавать список смешанных triangles, circlesи rectangles. И относитесь к ним как к однотипным объектам.

Затем, если этот список пытается вычислить поверхность для элемента, правильный метод будет найден и выполнен. Если элемент представляет собой треугольник, треугольникCalculateSurface()называется. Если круг - то круглаяCalculateSurface()называется. И так далее.

Если у вас есть функция, которая работает с фигурой, используя ее параметр, вам не нужно определять ее три раза - один раз для треугольника, круга и прямоугольника.

Вы можете определить его один раз и принять Figureкак аргумент. Передаете ли вы треугольник, круг или прямоугольник - если они реализуются CalculateParamter(), их тип не имеет значения.

Надеюсь, это помогло. Вы можете напрямую использовать те же самые объяснения на собеседовании.

Если вам что-то все еще трудно понять - не стесняйтесь спрашивать в комментариях ниже.

Что дальше?

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

Далее я сосредоточусь на том, что работодатели хотят видеть в младшем разработчике и как выделиться из толпы при поиске работы.

Следите за обновлениями.