Разница между объектом и экземпляром, есть ли она вообще?


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

Что такое куча (heap)?


Для детального разбора сначала вспомним, что все ссылочные типы (классы, интерфейсы, делегаты, коллекции, массивы и т.п.) хранятся в области памяти под названием куча, а все значимые типы (int, float, double, перечисления, структуры и т.п.) и ссылки на адреса памяти ссылочных типов на куче хранятся в стеке. Куча — динамическая, неупорядоченная область памяти, она намного больше стека и с этого уже можно сделать логический вывод, почему все ссылочные «объемные» типы хранятся там.

Создание объекта и экземпляра


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

 public class MyExample //класс-пример
    {
        public void Hi()
        {
            myHi();
        }
        private void myHi()
        {
            Console.WriteLine("Hi, man!!!");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            MyExample myExample = new MyExample(); //Тут я создаю переменную типа MyExample и 
            //присваиваю ей ссылку на экземпляр класcа MyExample

            myExample.Hi(); // использую объект класа MyExample
        }
    }

Простенький пример, к которому нужно еще додать очень многое. Во-первых, само понятие экземпляр подразумевает под собой набор значений нестатически полей для данного объекта (кто знаком со статикой поймёт скорее), а сам объект хранит в себе все методы и статические поля. На куче это выглядит так:

image

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

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

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


Выше я упомянул первую (важно, что именно первую) парадигму ООП — инкапсуляцию. Многие «новые» программисты путают инкапсуляцию со схожим явлением — сокрытием реализации. Эти неверные мысли идут из утверждения, что инкапсуляция — сокрытие реализации от пользователя благодаря модификаторам что доступа, что верно и в корне неверно одновременно. Если еще раз взглянуть на фото-пример и внимательно перечитать информацию, можно сделать вывод, что инкапсуляция это «некое объединение экземпляра и объекта в одну сущность». И в принципе — так и есть от части. Ведь правильное значение слова инкапсуляции в программировании будет звучать так: «Инкапсуляция — первая парадигма ООП, которая подразумевает, что данные и методы для работы с этими данными будут объединены в один объект [Объект 1(см. фото)], а реализация будет сокрыта от пользователя».

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

Комментарии (16)


  1. sashocq
    22.10.2019 15:55
    +2

    Сложилось ощущение, что автор не перечитал текст, который сам написал.
    Какая-то мешанина из разных слов получилась.


  1. Klenov_s
    22.10.2019 16:19
    +2

    Это сейчас стало модным, придумать какое-то бредовое высказывание, а потом писать целую статью, опровергающую его, но так и не родить ничего осмысленного?


  1. Ascar
    22.10.2019 16:39
    +1

    Мне кажется автор пытает рассказать что то про объект-тип… Кстати если упаковать данные значимого типа, то они окажутся «на куче». Так же если они в классе.


  1. ZXZs
    22.10.2019 20:33
    +1

    Я, вроде, понял, про что статья, но тут то ли какая-то подмена понятий, то ли ещё чего, но меня всё ещё что-то смущает.


    1. Klenov_s
      22.10.2019 20:38

      Просто автор сам придумал некую свою формулировку инкапсуляции, а потом пытается ее опровергнуть придумывая разницу между объектом класса и экземпляром класса.
      P.S. Это он еще не знает, что в TP объектом назывался класс )))


      1. ZXZs
        22.10.2019 21:13

        Я так понял автор имел ввиду то, что экземпляр – это поля, а объект – методы для работы с ними, поэтому экземпляров много, а объект один…


        1. Klenov_s
          22.10.2019 21:16

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


          1. ZXZs
            22.10.2019 21:19

            Все так и есть, но автор решил назвать вещи своими именами, от того и путаница.


          1. igormu
            23.10.2019 07:46

            Существуют языки с объектами без классов.


      1. VolCh
        23.10.2019 00:49

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


  1. Ryppka
    22.10.2019 22:11

    Если еще раз взглянуть на фото-пример и внимательно перечитать информацию, можно сделать вывод, что инкапсуляция это «некое объединение экземпляра и объекта в одну сущность».

    А все это объединение в одну сущность сводится к добавлению неявного аргумента-указателя))). В некоторых языках даже явного. А разговоров-то…


  1. Orange11Sky
    22.10.2019 22:52
    +2

    Как-то всё запуталось: где обьект, где экземпляр?
    Кто на ком стоял? ©
    C точки зрения языка есть класс как описание обьекта и экземпляр класса как обьект, созданный по его описанию.


  1. shiotiny
    23.10.2019 06:22

    Для детального разбора сначала вспомним, что все ссылочные типы (классы, интерфейсы, делегаты, коллекции, массивы и т.п.) хранятся в области памяти под названием куча, а все значимые типы (int, float, double, перечисления, структуры и т.п.) и ссылки на адреса памяти ссылочных типов на куче хранятся в стеке.


    Простите, но это не так! Все зависит от того как и где создан экземпляр класса.

    Скажем, на С++ описан класс. Он имеет поля (int, float, double).

    Если экземпляр класса создан как глобальная переменная — то его поля (int, float, double) будут храниться вообще вообще в сегменте статической памяти.

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

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

    Поля и методы с модификатором static тоже хранятся в в сегменте статической памяти.

    И так далее. В общем — все не так однозначно:)


    1. MaxKot
      23.10.2019 20:17

      Просто в первом абзаце речь шла об ООП вообще, а во втором повествование перескочило на .NET.


  1. a1ex322
    23.10.2019 23:53

    А есть ещё источники помимо этой статьи где объект != экземпляр?


    1. Ryppka
      24.10.2019 14:15

      В стандартах C и C++ объектом считается адресуемая область некоего хранилища, содержащая некое значение. В самом широком смысле этих понятий)