Что такое объект в программировании
Перейти к содержимому

Что такое объект в программировании

  • автор:

Что такое объект в программировании

Название «Объектно-ориентированное программирование» говорит само за себя. Центром внимания ООП является объект.

Давайте оглянемся вокруг. Вот побежала собака, стоит дом, стоит велосипед. Каким понятием можно объединить все эти понятия ? Возможно — предмет, но, как мне кажется, правильнее было бы применить слово объект. Если проводить дальнейшую аналогию, то можно сказать, что все что нас окружает — это объекты (в том числе и человек), а реальная жизнь состоит из взаимодействия этих объектов. Понятие объекта в ООП во многом приближено к привычному определению понятия объекта в реальном мире.

  1. имеет какое-то состояние (или находится в каком-то состоянии). К примеру, про собаку можно сказать, что она имеет имя, окраску, возраст, голодна она или нет и т.д.
  2. имеет определенное поведение. Т.е., та же собака может вилять хвостом, есть, лаять, прыгать и т.д.

А теперь рассмотрим формальное определение объекта в ООП:

Объект— это осязаемая сущность, которая четко проявляет свое поведение.

  • имя объекта;
  • состояние (переменные состояния);
  • методы (операции).

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

Объект ООП — это совокупность переменных состояния и связанных с ними методов(операций). Эти методы определяют как объект взаимодействует с окружающим миром.

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

А теперь в двух словах о нескольких терминах ООП:

Класс (class) — это группа данных и методов(функций) для работы с этими данными. Это шаблон. Объекты с одинаковыми свойствами, то есть с одинаковыми наборами переменных состояния и методов, образуют класс.

Объект (object)— это конкретная реализация, экземпляр класса. В программировании отношения объекта и класса можно сравнить с описанием переменной, где сама переменная(объект) является экземпляром какого-либо типа данных(класса).

Обычно, если объекты соответствуют конкретным сущностям реального мира, то классы являются некими абстракциями, выступающими в роли понятий. Понятие класса и что он в себя включает мы рассмотрим отдельно. А на данном этапе воспринимайте класс как шаблон объекта. Для формирования какого-либо реального объекта необходимо иметь шаблон, на основании которого и строится создаваемый объект. При рассмотрении основ ООП мы часто смешиваем понятие объекта и класса. Дело в том, что класс — это некоторое абстрактное понятие. Для проведения аналогий или приведения примеров оно не очень подходит. На много проще приводить примеры, основываясь на объектах из реального мира, а не на абстрактных понятиях. Поэтому, говоря, к примеру, про наследование мы прежде всего имеем ввиду наследование классов(шаблонов), а не объектов, хотя часто и применяем слово объект. Скажем так: объект — это физическая реализация класса(шаблона).

Методы (methods)— это функции(процедуры), принадлежащие классу.

Сообщение (message)— это практически тоже самое, что и вызов функций в обычном программировании. В ООП обычно употребляется выражение «послать сообщение» какому-либо объекту. Понятие «сообщение» в ООП можно объяснить с точки зрения основ ООП: мы не можем напрямую изменить состояние объекта и должны как бы послать сообщение объекту, что мы хотим так и так изменить его состояние. Объект сам меняет свое состояние, а мы только его просим об этом посылая сообщения.

Возможно некоторые моменты пока не очевидны для Вас. Уверен, что основные понятия ООП объяснят все возникающие на данном этапе вопросы.

Что такое объект

Недавно работал над задачей. Нужно было получить из сети некоторые объекты по REST и обработать.

Ну все вроде бы ничего сложного. Загрузил, спарсил, вернул. Ок. Затем нужно было полученный массив обработать. Вкратце, по особой логике просуммировать некоторые поля — это могла быть строка, число или null. Начал делать как обычно: создал переменную sum, начал цикл for, в нем начал заниматься основной логикой. Закончил.

Продолжил кодить. Хоба! Эта же логика. Не стал копипастить, вынес в отдельную функцию. Тоже все хорошо.

Начал заниматься 3 задачей. Объединить результаты нескольких вычислений. Опять циклом начал перебирать. Но тут появилась мысль:

“А что, если создать для этого отдельный объект?”

Да нет, чушь! Ведь не существует в реальном мире ОбъединителяКакогоТоРезультата. Но что, если сделать? Попробуем.

Какого. Почему все вмиг стало так просто? Передал в конструктор нужные объекты и сделал методы, которые применяли свою логику к содержащимся в них объектам. Всего-лишь несколько строчек! Почему я так раньше не делал?

Я раззадорился. Начал видеть объекты везде. Это очень удобно: не нужно смотреть на каждый фрагмент кода с мыслью “а было ли это где нибудь раньше?”. А как тестировать легче стало!

Тут до меня дошло, что было со мной не так:

Я не разграничивал объекты реального мира и объекты в понимании ООП.

Объекты ООП != Объекты реального мира

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

  • DTO
  • Объекты из реального мира
  • Объекты, реализующие какой-то интерфейс (обычно для запросов по сети, для использования в DI контейнера)

Оглядевшись назад понял, что все дороги вели именно к такому мышлению:

  • В вузе нас учили ООП по каким-то моделям типа: “Вот это объект Человек. У него есть атрибуты Имя и Возраст”, а когда дело доходило до программирования, никто не смотрел как мы пишем код. Получалась каша из императивного программирования и набросков объектов.
  • Во всяких обучающих ресурсах (видео, книги, курсы) дают слишком простые примеры. Примеры слишком прямолинейные (как в выше перечисленном вузе). Не дают почувствовать мощь объектов.
  • Если были задачи, то слишком простые. Не тот уровень сложности, чтобы действительно над чем-то задуматься (например, приевшийся калькулятор). Они не показывали, что объекты могли бы решить многие проблемы.

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

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

Диаграммы мешают в понимании ООП

Но что насчет популярных инструментов проектирования? Нотаций. Наверное все видели различные UML диаграммы. Диаграмму классов так наверное любой программист должен был видеть хоть раз.

Взято с https://medium.com/@uferesamuel/uml-class-diagrams-the-simple-approach-eee2d1ffc125

ER диаграммы тоже хороши — они слишком сильно сцеплены с реальным миром. Там почти все представляет объекты реального мира.

Взято с https://online.visual-paradigm.com/diagrams/templates/chen-entity-relationship-diagram/see-doctor-erd-chen-notation/

Поразмыслив, я понял 3 вещи:

  1. ER диаграмма ничего не имеет общего с ООП — это инструмент для бизнес-анализа. Я не обязан создавать такие же классы, как и на этой диаграмме. Кто мне такое сказал?
  2. UML показывает высокоуровневую структуру программы: кто в ней есть и что они должны делать/иметь. Т.е. что делать, а не как делать. Реализация ложится на плечи программиста (спойлер, это будут методы на 100+ строк из циклов, условий и других прелестей)
  3. Многие нотации ориентированы для простого понимания концепций программы — из каких компонентов состоит. Ничто не мешает нам вместо классов передавать массивы object. Не нужно ориентироваться на них как на истину в первой инстанции.

В итоге заканчиваем, тем что имеем много объектов. Ура, ООП! А что внутри? Громадные циклы на десятки строк, множество флагов и if’ов — полная императивщина.

Да о чем я говорю?

Что же я понял? Например,

public interface IWorkingScheduleService < // Возвращает тип дня: рабочий, предпраздничный, праздничный, выходной int GetDayType(DateOnly date); >
// Количество рабочих часов на каждый день недели public class UserSchedule < public float Monday < get; set; >public float Tuesday < get; set; >public float Wednesday < get; set; >public float Thursday < get; set; >public float Friday < get; set; >public float Saturday < get; set; >public float Sunday < get; set; >>

Задача — посчитать общее время рабочих часов.
Банально, да? Давайте сделаем функции:

public static class ScheduleHelpers < public static float GetTotalWorkingHours(IWorkingScheduleService service, UserSchedule schedule, DateOnly from, DateOnly to) < // Какая-то логика return 0; >public static float GetTotalWorkingHoursWithoutPreholiday(IWorkingScheduleService service, UserSchedule schedule, DateOnly from, DateOnly to) < // Какая-то логика return 0; >public static float GetTotalHolidayWorkingHours(IWorkingScheduleService service, UserSchedule schedule, DateOnly from, DateOnly to) < // Какая-то логика return 0; >> 

Но тут мы заметим общую начальную часть: IWorkingScheduleService service, UserSchedule schedule . Почему бы нам не вынести эту логику в отдельный объект?

public class WorkingScheduleCalculator < private readonly IWorkingScheduleService _service; private readonly UserSchedule _schedule; public WorkingScheduleCalculator(IWorkingScheduleService service, UserSchedule schedule) < _service = service; _schedule = schedule; >public float GetTotalWorkingHours(DateOnly from, DateOnly to) < // Какая-то логика return 0; >public float GetTotalWorkingHoursWithoutPreholiday(DateOnly from, DateOnly to) < // Какая-то логика return 0; >public float GetTotalHolidayWorkingHours(DateOnly from, DateOnly to) < // Какая-то логика return 0; >>

Как же стало удобно! Все находится рядом, сигнатуры стали короче и поддержка автодополнения в подарок — прелесть!

Выводы

Что я вынес из всего этого?

  1. Объект это не концепция реального мира. Можно сделать объект который имеет имя, атрибуты, поведение, как у объекта реального мира, сделать максимально похожим, но это НЕ ОБЪЕКТ РЕАЛЬНОГО МИРА. Надо прекратить думать в данном ключе! Объект — это (всего лишь) данные и функции, ассоциированные с ними
  2. На каждый блок с логикой (цикл, последовательность условий и т.д.) я смотрю с мыслью: “Нельзя ли вынести это в отдельный объект?”
  3. Таким же образом, смотрю на функции, которые принимают одинаковые аргументы. Их всех можно объединить в объекты, атрибутами которых являются эти общие аргументы.

P.S. Я не радикал, а за осмысленное и прагматичное использование объектов: для тривиальной логики можно оставить циклы, разрешаю)

Объект (программирование)

Объект в программировании — некоторая сущность в виртуальном пространстве, обладающая определённым состоянием и поведением, имеющая заданные значения свойств (атрибутов) и операций над ними (методов) [1] . Как правило, при рассмотрении объектов выделяется то, что объекты принадлежат одному или нескольким классам, которые определяют поведение (являются моделью) объекта. Термины «экземпляр класса» и «объект» взаимозаменяемы. [2]

Объект, наряду с понятием класс, является важным понятием объектно-ориентированного подхода. Объекты обладают свойствами наследования, инкапсуляции и полиморфизма [1] .

Термин объект в программном обеспечении впервые был введен в языке Simula и применялся для моделирования реальности [2] .

Связанные понятия

Экземпляр класса (англ. instance ) — это описание конкретного объекта в памяти. Класс описывает свойства и методы, которые будут доступны у объекта, построенного по описанию, заложенному в классе. Экземпляры используют для представления (моделирования) конкретных сущностей реального мира. Например, экземпляром класса стиральных машин может быть ваша стиральная машина, имеющая следующие свойства: компания-производитель «Вятка», наименование модели «Вятка-автомат», серийный номер изделия ВЯТ454647, емкость 20 л. В отличие от имени класса, имя экземпляра обычно начинается со строчной буквы.

Инстанцирование (англ. instantiation ) — создание экземпляра класса. В отличие от слова «создание», применяется не к объекту, а к классу. То есть, говорят: (в виртуальной среде) создать экземпляр класса или, другими словами, инстанцировать класс. Порождающие шаблоны используют полиморфное инстанцирование.

Анонимный объект (англ. anonymous object ) — это объект, который принадлежит некоторому классу, но не имеет имени.

Инициализация (англ. initialization ) — присвоение начальных значений полям объекта.

Время жизни объекта — время с момента создания объекта (конструкция) до его уничтожения (деструкция).

Практический подход

За исключением прототипно-ориентированных языков вроде Lua и JavaScript, где понятие «класс» не используется вовсе, в большинстве объектно-ориентированных языков программирования (таких как Java, C++ или C#), объекты являются экземплярами некоторого заранее описанного класса.

Объекты в таких языках создаются с помощью конструктора класса, и уничтожаются либо с помощью деструктора класса (например, в C++), либо автоматически с использованием сборщика мусора (например, в Java и C#), либо используя внутренний счётчик ссылок на объект и сообщения («dealloc» в Objective-C). (C# поддерживает деструкторы, но они вызываются сборщиком мусора.) Объект хранится в виде данных всех его полей и ссылок на таблицу виртуальных методов и RTTI своего класса. Класс определяет набор функций и служебной информации для построения объекта, в том числе необходимый объем памяти для хранения объекта.

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

Пример кода

Пример создания нового объекта и работы с ним в языке программирования Java:

// Создание экземпляра класса ArrayList с именем list ArrayList list = new ArrayList(); // Добавление экземпляров класса Integer в объект list list.add(new Integer(1)); list.add(new Integer(2)); list.add(new Integer(3)); 

Подразумевается, что класс ArrayList уже описан в программном коде и его описание содержит определение для конструктора класса и метода add .

Примечания

  1. 12Словарь по естественным наукам — «Объект».
  2. 12Гради Буч. Объектно-ориентированный анализ и проектирование с примерами приложений на С++, Классы и объекты

Литература

  • Гради Буч. Объектно-ориентированный анализ и проектирование с примерами приложений на С++. — Бином, 1998. — ISBN 0-8053-5340-2, ISBN 5-7989-0067-3, ISBN 5-7940-0017-1
  • Дополнить статью (статья слишком короткая либо содержит лишь словарное определение).
  • Найти и оформить в виде сносок ссылки на авторитетные источники, подтверждающие написанное.
  • Проставив сноски, внести более точные указания на источники.

Что такое объект в программировании

Доброго времени суток! Настало время поговорить о таких понятиях как класс и объект в контексте объектно-ориентированного программирования и языка C#. На самом деле, мы уже не раз сталкивались с классами и объектами, тот же метод «Main» (в котором мы пишем практически весь код) принадлежит классу «Program».

Можно сказать, что класс – это описание какого-то типа данных. Это некий абстрактный шаблон (набор правил), по которому мы можем создавать объекты (переменные, того типа данных, который описывает класс). Объект – это созданный экземпляр класса. Например, есть класс «Студент», который характеризует среднестатистического студента (с фамилией, именем, возрастом и т.п.), а есть конкретный студент Иванов Иван 20-ти лет. Вот в данном случае, Иванов Иван 20-ти лет как раз и является экземпляром класса! Т.е. конкретно существующей сущностью. Или другой пример, форма для выпечки хлеба является своего рода «классом», а выпеченные в ней булки хлеба – экземплярами. А теперь разберемся как создавать классы.

Хотя, на практике, Вам чаще придется работать с объектами классов, который создали не Вы (например, с объектами стандартных классов)…

И так, вот самый простой пример создания класса:

//Класс, описывающий простого студента class Student < //Тело класса >

В данном примере создан самый простой класса с именем «Student», это вообще пустой класс, но даже такой класс может быть полезен на практике! Так по каким же правилам создаются классы? В самом простом случае указывается ключевое слово class после которого, через пробел, указывается название класса (в нашем случае «Student»). После названия класса, в фигурных скобках идет тело класса. А теперь давайте посмотрим, как можно создать объекты класса «Student»:

Student firstStudent = new Student();

Объекты классов, создаются почти так же, как и переменные стандартных типов, только после знака «=» мы используем ключевое слово new и дальше снова повторяем имя класса с круглыми скобками после него.

Очень похоже на вызов метода. Позже Вы поймете почему так!

Но на практике от такого «студента» толка будет мало, так как наш класс пустой… Так что, давайте заполним тело класса полезным содержимым! В этом уроке мы рассмотрим, как «заполнять» тело класса полями и методами.

Сначала разберемся с полями класса. Создаются они практически так же, как мы создавали переменные в методах, только есть одно отличие, перед полем класса желательно указать уровень доступа к нему. А указывается он с помощью одного из ключевых слов (модификаторов доступа), таких как public (доступ открыт) и private (доступ закрыт).

В C# есть еще и другие модификаторы доступа, но на данном этапе они нам пока не нужны.

Так вот, давайте заполним наш пустой класс несколькими полями, чтобы посмотреть на практике, как это делается:

//Класс, описывающий простого студента class Student < //Тело класса public string name; //Имя студента public uint grade; //Курс >

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

//Создаем объект-студента (пока "безликого") Student ivanStudent = new Student(); //Задаем значения полей объекта ivanStudent.name = "Иван"; //Задаем имя ivanStudent.grade = 2; //Задаем курс

Всю работу мы сделали в два этапа, сначала создали «безликого» студента (создали новый объект класса), а потом задали значения полям объекта.

Обратите внимание как мы получаем доступ к полям объекта, сначала мы указываем имя объекта, а затем, через точку ­– имя поля. Обращение к методам и свойствам осуществляется так же.

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

Но на практике так лучше не делать. Как правило, поля классов делают закрытыми, чтобы пользователь класса не мог работать с ними на прямую. Потому, что каждый объект – это сложная система, которая «живет» по своим правилам, и некорректное вмешательство из вне, может привести к нарушению целостности!

Если бы мы объявили поля класса закрытыми, т.е. вместо слова public написали слово private, то подобного рода код, просто не компилировался:

//Задаем значения полей объекта ivanStudent.name = "Иван"; //Задаем имя ivanStudent.grade = 2; //Задаем курс

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

Внутри методов класса (как открытых, так и закрытых), можно получить доступ к любому, даже самому закрытому полю класса!

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

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

//Класс, описывающий простого студента class Student < //Возвращает значение поля name public string GetName() < return name; >//Возвращает значение поля grade public uint GetGrade() < return grade; >//Устанавливает значение поля name public void SetName(string aName) < name = aName; >//Устанавливает значение поля grade public void SetGrade(uint aGrade) < grade = aGrade; >//Тело класса private string name; //Имя студента private uint grade; //Курс >

Теперь, задать значения полям объекта можно только так:

//Создаем объект-студента (пока "безликого") Student ivanStudent = new Student(); //Задаем значения полей объекта ivanStudent.SetName("Иван"); //Задаем имя ivanStudent.SetGrade(2); //Задаем курс

На самом деле, в нашем случае, методы, устанавливающие значения полям, не особо отличаются функциональностью, но на практике, часто такие методы могут быть оснащены дополнительными проверками аргументов, например, методы могли бы не устанавливать слишком длинные имена, или курс старше шестого…

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *