Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
пп (кроме 1,21,37).docx
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
182.5 Кб
Скачать

29. Классы. Инкапсуляция. Сокрытие данных и видимость членов класса. Идиома «pimpl».

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

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

В языках программирования инкапсуля́ция имеет одно из следующих значений, либо их комбинацию:

-языковой механизм ограничения доступа к определённым компонентам объекта;

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

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

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

Сокрытие реализации целесообразно применять в следующих целях:

-предельная локализация изменений при необходимости таких изменений,

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

Два метода сокрытия данных

Один из них может использоваться хакерами для того, чтобы скрыть вре­доносный код; второй вы можете применять сами для защиты конфиден­циальных файлов

сокрытия данных: потоки данных NTFS (известные также как альтернативные потоки данных) и доступ к списку ресурсов на базе разрешений Access-basedEnumeration (ABE).

Видимость членов класса

Каждое поле, метод или свойство класса имеет атрибут видимости. В PascalABC.NET существуют четыре типа атрибутов видимости: public (открытый), private (закрытый), protected (защищенный) и internal (внутренний). К члену класса, имеющему атрибут public, можно обратиться из любого места программы, члены класса с атрибутом private доступны только внутри методов этого класса, члены класса с атрибутом protected доступны внутри методов этого класса и всех его подклассов, члены класса с атрибутом internal доступны внутри сборки (термин .NET, сборка в нашем понимании - это множество файлов, необходимых для генерации .exe или .dll-файла). Кроме того, private и protected члены видны отовсюду в пределах модуля, в котором определен класс.

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

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

type

A = class

private

x: integer;

protected

a: integer;

public

constructor Create(xx: integer);

begin

x := xx; // верно, т.к. внутри метода класса можно обращаться к его закрытому полю x

a := 0; // верно

end;

end;

Следующий же код располагается в другом модуле:

type

B = class(A)

public

procedure print;

begin

writeln(a); // верно, т.к. a - защищенное поле

writeln(x); // неверно, т.к. х - закрытое поле

end;

end;

...

varb1: B := newB(5);

...

writeln(b1.x); // неверно, т.к. х - закрытое поле

writeln(b1.a); // неверно, т.к. a - защищенное поле

b1.print; // верно, т.к. print - открытый метод

Идиомы Pimpl– указатель на реализацию

Допустим, нам необходимо написать кроссплатформенное сетевое приложение с использованием сокетов. Для этого нам необходим класс GeneralSocket (“Видимый класс”) , который будет инкапсулировать в себе детали реализации конкретной платформы (“Скрываемый класс”). Часто требуется скрыть детали реализации от пользователей или других разработчиков:

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

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

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