Как сделать инкапсуляцию в java

Обновлено: 06.07.2024

Эта статья рассказывает про основные принципы ООП в Java ( инкапсуляция, наследовании, полиморфизм и абстракции ).

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

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

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

Наследование – принцип ООП в Jаva , согласно которому объект может наследовать атрибуты другого объекта. Это позволяет программисту создавать похожие объекты без повторного переопределения атрибутов:

В теоретических основах ООП это означает, что каждая собака, кошка и птица ( подклассы ) будут иметь атрибуты имени и возраста. А также метод Identify , потому что они являются животными ( принадлежат суперклассу Animal ).

Полиморфизм

Перегрузка : имя метода остается неизменным, но параметры, возвращаемый тип и количество параметров могут изменяться:

Перегрузка в основах ООП – это когда метод подкласса имеет то же имя, параметры и возвращаемый тип, что и метод в суперклассе, но реализуется по-другому:

Несколько правил переопределения метода в основах ООП Java :

  • Методы подкласса должны иметь одинаковый возвращаемый тип и аргументы;
  • Уровень доступа метода подкласса не может быть более низким, чем у метода суперкласса;
  • Метод, объявленный завершенным или статическим, нельзя переопределить;
  • Если метод не может быть унаследован, его нельзя переопределить.

Абстракция в ООП на Java

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

Если я в чем-то ошибся описывая 4 принципа ООП в Java или вы чего-то не поняли про объектно ориентированное программирование Java, напишите об этом в комментариях.

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

Пожалуйста, оставляйте свои мнения по текущей теме статьи. Мы крайне благодарны вам за ваши комментарии, лайки, дизлайки, отклики, подписки!

Аналогично, когда вы хотите обновить состояние компонента React с помощью useState или setState, эти изменения не влияют непосредственно на состояние компонента. Вместо этого они ставятся в очередь потенциальные изменения состояния, которые применяются после завершения цикла рендеринга. Вы напрямую не устанавливаете состояние компонента React, это делает сам React;

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

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

Инкапсуляция является одним из подходов к решению этой проблемы.

Инкапсуляция также решает еще одну интересную проблему. Представьте, что у вас есть совокупность данных, которые нужно обработать. Один из способов сделать это — сначала выбрать структуру данных для представления. Если вы начнете с реализации (скажем, используете массив), и все, кто его использует, узнает о его структуре то это может создать тесную связь со структурой данных, что может затруднить изменение этой реализации позже. Что, если вы в конечном итоге захотите поменять массив на поток (stream), дерево или какую-то другую структуру данных? Если все узнают реализацию, это может быть слишком поздно.

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

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

Когда Брендан Айх создал JavaScript в эти роковые 10 дней, кульминацией которых стал выпуск в 1995 году, он задумал две идеи:

  • Использования языка программирования Scheme в браузере
  • Все должно выглядеть как в языке Java

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

Java — это объектно-ориентированный язык на основе классов. От Java JavaScript получил понятие функций конструктора, (в конце концов) классы и ключевого слова new (среди прочего).

Так же Брендан Айх черпал свое вдохновение от языка программирования Self. От него он взял прототипное наследование, которые делают JavaScript гораздо более мощным и гибким, чем его аналогично названный, но в остальном дальний родственник, Java, но это уже другая история.

Спустя 23 года этот парадигмальный плавильный котел все еще немного неправильно понят. Одно из таких распространенных недоразумений связано с инкапсуляцией.

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

До появления предложения о приватных полях (private fields proposal) в ECMAScript не было никакого способа создать честное приватное свойство для объектов в JavaScript. Вместо того, чтобы использовать замыкания, с помощью которых обычно создают приватные данные для объектов в JavaScript, некоторые разработчики решили обозначить частные свойства и методы, добавив к ним префикс подчеркивания, и это стало общепризнанным (хотя и неуклюжим и спорным) соглашением.

Это спорно по нескольким причинам:

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

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

Расширенная поверхность атаки для хакеров: в частности, для общедоступных API-интерфейсов добавление еще большего количества API, чем необходимо для использования вашего кода, расширяет доступные данные для использования злоумышленниками. Один из важнейших принципов обеспечения безопасности программного обеспечения ограничивает поверхность атаки только тем, что абсолютно необходимо. Если вы действительно намереваетесь использовать что-то только для внутреннего использования, оно не должно подвергаться внешнему воздействию.

Самодокументируемый код: Ваш общедоступный API должен быть максимально самодокументируемым. Один из способов сделать это — показать только те методы и свойства, которые вы собираетесь предоставить своим пользователям. Таким образом, пользователи не склонны использовать неподдерживаемые и недокументированные методы. Если вы используете соглашение о подчеркивании, вы полагаетесь на то, что пользователь знает, что это значит, и понимает, что вы не хотите что бы это было ими использовано. Если вы используете инкапсуляцию, вам не нужно беспокоиться об этом. Они не смогут использовать то, к чему у них нет доступа.

Конечно, как известно JavaScript всегда поддерживал реальную инкапсуляцию данных. Очень легко объявить приватные данные в JavaScript.

Используем Замыкание

Привилегированный метод — это метод, который имеет доступ к закрытым данным внутри области действия функции (также известной как лексическая среда). Привилегированные функции и методы имеют доступ на основе ссылок к переменным внутри функции, даже после того, как функция завершилась. Эти ссылки являются действующими, поэтому, если состояние изменяется во внутренней функции, изменения переносятся в каждую привилегированную функцию. Другими словами, когда мы вызываем counter.click(), она изменяет значение, которое видит counter.getCount().

Можно даже наследовать приватное состояние, используя функциональные миксины.

Использование приватных полей

На момент написания этой статьи закрытые поля стали доступны в babel с включенной функцией stage-3. Они так же поддерживаются в Chrome, Opera, браузере Android и Chrome для Android, поэтому есть хороший шанс, что вы можете сделать что-то вроде этого:

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

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

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


// Java-программа для демонстрации инкапсуляции

public class Encapsulate

// объявлены приватные переменные

// к ним может получить доступ только

// публичные методы класса

private String geekName;

private int geekRoll;

private int geekAge;

// получить метод доступа к возрасту

// приватная переменная geekAge

public int getAge()

// получить метод для доступа к имени

// приватная переменная geekName

public String getName()

// получить метод для доступа к roll

// приватная переменная geekRoll

public int getRoll()

// установить метод доступа к возрасту

// приватная переменная geekage

public void setAge( int newAge)

// установить метод для доступа к имени

// приватная переменная geekName

public void setName(String newName)

// установить метод для доступа к roll

// приватная переменная geekRoll

public void setRoll( int newRoll)

В приведенной выше программе класс EncapsulateDemo инкапсулирован, поскольку переменные объявлены как закрытые. Методы get, такие как getAge (), getName (), getRoll (), устанавливаются как открытые, эти методы используются для доступа к этим переменным. Методы установки, такие как setName (), setAge (), setRoll (), также объявляются как публичные и используются для установки значений переменных.

Программа для доступа к переменным класса EncapsulateDemo показана ниже:

public class TestEncapsulation

public static void main (String[] args)

Encapsulate obj = new Encapsulate();

// установка значений переменных

// Отображение значений переменных

System.out.println( "Geek's name: " + obj.getName());

System.out.println( "Geek's age: " + obj.getAge());

System.out.println( "Geek's roll: " + obj.getRoll());

// Прямой доступ к geekRoll невозможен

// System.out.println ("Geek's roll:" + obj.geekName);

Преимущества инкапсуляции :

  • Сокрытие данных: пользователь не будет иметь представления о внутренней реализации класса. Пользователю не будет видно, как класс хранит значения в переменных. Он только знает, что мы передаем значения методу-установщику, и переменные инициализируются с этим значением.
  • Повышенная гибкость: мы можем сделать переменные класса доступными только для чтения или только для записи, в зависимости от наших требований. Если мы хотим сделать переменные доступными только для чтения, мы должны опустить методы setter, такие как setName (), setAge () и т. Д. Из вышеприведенной программы, или если мы хотим сделать переменные доступными только для записи, мы должны опустить методы get, такие как getName (), getAge () и т. д. из вышеуказанной программы
  • Возможность многократного использования. Инкапсуляция также улучшает возможности повторного использования и позволяет легко менять ее в соответствии с новыми требованиями.
  • Тестировать код легко: инкапсулированный код легко тестировать для модульного тестирования.

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

Инкапсуляция (encapsulation) — это сокрытие реализации класса и отделение его внутреннего представления от внешнего (интерфейса). При использовании объектно-ориентированного подхода не принято применять прямой доступ к свойствам какого-либо класса из методов других классов. Для доступа к свойствам класса принято задействовать специальные методы этого класса для получения и изменения его свойств.

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

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

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

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

Читайте также: