Перейти к содержимому

В чем разница инкапсуляции и сокрытия

  • автор:

В чем разница инкапсуляции и сокрытия?

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

комментировать

в избранное ссылка отблагодарить

Инкапсулируй это

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

Противоположность инкапсуляции — размазывание знаний о функционировании чего-либо по всей программе.

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

Пример: работа с денежными величинами. Не секрет, что во многих e-commerce системах денежные величины реализованы в виде чисел с плавающей запятой. Думаю, все из нас в курсе, что при простом сложении двух «целых» чисел, представленных в виде переменных с плавающих запятой, может образоваться «немного не целое число». Поэтому при такой реализации там и тут приходится вставлять вызов функции округления. Это и есть размазывание знаний об устройстве сущности по всей программе. Инкапсуляция в данном случае — собрать (спрятать) в одном месте знание о том, что деньги представлены в виде величины с плавающей запятой, и что её постоянно приходится округлять при самых невинных операциях. Спрятать так, чтобы при использовании сущности «деньги» речь об округлении даже не заходила. При инкапсуляции не будет никаких проблем заменить реализацию «денег» с числа с плавающей на число с фиксированной запятой.

  • инкапсуляция
  • сокрытие реализации
  • Программирование
  • Совершенный код

Вопросы на собеседованиях по C# и .Net. На позицию junior/middle. Часть 6.

Мы создали свой сайт! Все материалы, опубликованные в этом блоге, переехали туда.

Наш новый сайт maddevelop.ru

А данную статью вы можете найти по ссылке ниже:

P.S. движок teletype.in очень странно интерпретирует ссылку, и пришлось вставлять ее полным текстом

Вопрос 42

В чем разница инкапсуляции и сокрытия?

Ответ: Инкапсуляция — одна из парадигм ООП. Она представляет собой способность языка упаковывать определённые участки кода в контейнеры, исключая возможность внешнего мира нарушения целостности данного кода. Основной единицей инкапсуляции в C# является класс. Инкапсуляция позволяет структурировать код и помогает обезопасить его от многих возможных проблем, относительно защиты данных и информации.

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

Но сам термин «сокрытие» лучше употреблять в контексте методов. Сокрытие метода представляет собой реализация тела метода в дочернем классе, сигнатура которого соответствует сигнатуре метода в родительском классе. Для сокрытия применяется ключевое слово «new».

class Animal < public void Say() < Console.WriteLine("*Some sounds*"); >> class Cat:Animal < public new void Say()// the usage of hiding technique < Console.WriteLine("Miew!"); >>

Лучше термин «сокрытие» использовать в контексте именно сокрытия метода, потому что нет определённого правила отличия инкапсуляции и сокрытия, и на этом фоне могут плявляться разные споры.

Вопрос 43

Что такое частные и общие сборки?

Ответ: Частные сборки:

  • Видны только самому приложению
  • Нет необходимости заботиться об уникальном имени во всем глобальном пространстве имен
  • Не нужно делать записей в реестре при развертывании приложения
  • Сборки просто копируются в директорию приложения или в подчинённую директорию
  • Общая среда выполнения (CLR) при запуске приложения прочитает его манифест и определит какие сборки необходимы. Затем будет произведен поиск нужной сборки по директории приложения (процесс зондирования)
  • Общие сборки могут быть использованы сразу несколькими приложениями
  • Сборка должна иметь строгое имя (strong name)
  • Сборка должна быть помещена в общедоступное место – Global Assembly Cache (GAC, глобальный кэш сборок)

Вопрос 44

Что такое .Net Framework?

Ответ: .NET Framework — программная платформа, выпущенная компанией Microsoft в 2002 году. Основой платформы является общеязыковая среда исполнения Common Language Runtime (CLR), которая подходит для разных языков программирования. Функциональные возможности CLR доступны в любых языках программирования, использующих эту среду.

Вопрос 45

Чем управляемый код (managed code) отличается от неуправляемого (unmanaged code)?

Ответ: Управля́емый код (managed code) — термин, введённый фирмой Microsoft, для обозначения кода программы, исполняемой под «управлением» виртуальной машины .NET — Common Language Runtime или Mono. При этом машинный код называется неуправля́емым кодом (unmanaged code).

Слово «управляемый» относится к методу обмена информацией между программой и исполняющей средой. Оно означает, что в любой точке исполнения управляющая среда может приостановить исполнение и получить информацию, специфичную для текущего состояния. Необходимая для этого информация представлена в управляемом коде на языке Intermediate Language и в связанных с этим кодом метаданных.

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

Вопрос 46

LINQ lazy loading, eager loading в чем разница

Ответ:

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

var query = context.Categories.Take(3); // Lazy loading foreach (var Category in query) < Console.WriteLine(Category.Name); foreach (var Product in Category.Products) < Console.WriteLine(Product.ProductID); >>

Таким образом сгенерируется следующий SQL код:

SELECT TOP (3) [c].[CatID] AS [CatID], [c].[Name] AS [Name], [c].[CreatedDate] AS [CreatedDate] FROM [dbo].[Category] AS [c] GO -- Region Parameters DECLARE @EntityKeyValue1 Int = 1 -- EndRegion SELECT [Extent1].[ProductID] AS [ProductID], [Extent1].[Name] AS [Name], [Extent1].[UnitPrice] AS [UnitPrice], [Extent1].[CatID] AS [CatID], [Extent1].[EntryDate] AS [EntryDate], [Extent1].[ExpiryDate] AS [ExpiryDate] FROM [dbo].[Product] AS [Extent1] WHERE [Extent1].[CatID] = @EntityKeyValue1 GO -- Region Parameters DECLARE @EntityKeyValue1 Int = 2 -- EndRegion SELECT [Extent1].[ProductID] AS [ProductID], [Extent1].[Name] AS [Name], [Extent1].[UnitPrice] AS [UnitPrice], [Extent1].[CatID] AS [CatID], [Extent1].[EntryDate] AS [EntryDate], [Extent1].[ExpiryDate] AS [ExpiryDate] FROM [dbo].[Product] AS [Extent1] WHERE [Extent1].[CatID] = @EntityKeyValue1 GO -- Region Parameters DECLARE @EntityKeyValue1 Int = 3 -- EndRegion SELECT [Extent1].[ProductID] AS [ProductID], [Extent1].[Name] AS [Name], [Extent1].[UnitPrice] AS [UnitPrice], [Extent1].[CatID] AS [CatID], [Extent1].[EntryDate] AS [EntryDate], [Extent1].[ExpiryDate] AS [ExpiryDate] FROM [dbo].[Product] AS [Extent1] WHERE [Extent1].[CatID] = @EntityKeyValue1

Как видно из примера, мы получаем 4 SQL запроса. Это означает, что будет происходить 4 обращения к базе данных, один раз для таблицы Categories и 3 раза для таблицы Products, которая связана с Categories. В этом случае дочерние объекты заполняются по запросу.

Можно отключить lazy loading. Для этого нужно установить параметр LazyLoadingEnabled свойства ContextOptions объекта контекста в состояние false. После этого можно будет получать зависимые от родителя объекты при единственном запросе.

context.ContextOptions.LazyLoadingEnabled = false;

В случае eager loading, зависимые объекты загружаются автоматически с родительской таблицей. Для того, чтобы использовать eager loading нужно применить метод Include().

var query = context.Categories.Include("Products").Take(3); // Eager loading foreach (var Category in query) < Console.WriteLine(Category.Name); foreach (var Product in Category.Products) < Console.WriteLine(Product.ProductID); >>

Сгенерированный SQL запрос:

SELECT [Project1].[CatID] AS [CatID], [Project1].[Name] AS [Name], [Project1].[CreatedDate] AS [CreatedDate], [Project1].[C1] AS [C1], [Project1].[ProductID] AS [ProductID], [Project1].[Name1] AS [Name1], [Project1].[UnitPrice] AS [UnitPrice], [Project1].[CatID1] AS [CatID1], [Project1].[EntryDate] AS [EntryDate], [Project1].[ExpiryDate] AS [ExpiryDate] FROM (SELECT [Limit1].[CatID] AS [CatID], [Limit1].[Name] AS [Name], [Limit1].[CreatedDate] AS [CreatedDate], [Extent2].[ProductID] AS [ProductID], [Extent2].[Name] AS [Name1], [Extent2].[UnitPrice] AS [UnitPrice], [Extent2].[CatID] AS [CatID1], [Extent2].[EntryDate] AS [EntryDate], [Extent2].[ExpiryDate] AS [ExpiryDate], CASE WHEN ([Extent2].[ProductID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1] FROM (SELECT TOP (3) [c].[CatID] AS [CatID], [c].[Name] AS [Name], [c].[CreatedDate] AS [CreatedDate] FROM [dbo].[Category] AS [c] ) AS [Limit1] LEFT OUTER JOIN [dbo].[Product] AS [Extent2] ON [Limit1].[CatID] = [Extent2].[CatID]) AS [Project1] ORDER BY [Project1].[CatID] ASC, [Project1].[C1] ASC

Как можно заметить имеется только один SQL запрос. А это означает, что обращение к базе данных будет происходить только единожды для таблицы Categories и Products зависящей от нее. Таким образом, полученная выборка будет сразу содержать данные от родительской и от дочерней таблицы.

Вопрос 47

Можно ли запретить наследование от своего собственного класса?

Ответ:

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

sealed class SomeClass < // Объявление класса >

Вопрос 48

Можно ли разрешить наследование класса, но запретить переопределение метода?

Ответ:

Да. Для этого нужно определить родительский класс с модификатором public, а метод в нем пометить как sealed.

class Base < public virtual void Test() < . >> class Subclass1 : Base < public sealed override void Test() < . >> class Subclass2 : Subclass1 < public override void Test() < . >// Не скомпилируется! >

Вопрос 49

Определение паттерна синглтон

Ответ:

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

Классическая реализация данного шаблона на C#:

class Singleton < private static Singleton instance; private Singleton() <>public static Singleton getInstance() < if (instance == null) instance = new Singleton(); return instance; >>

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

Вопрос 50

Thread, task, примеры использования?

Ответ:

Класс Thread, позволяет выделить, которые будут выполняться одновременно.

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

Для запуска потока вызывается метод Start.

using System.Threading; class Program < static void Main(string[] args) < // создаем новый поток Thread myThread = new Thread(new ThreadStart(Count)); myThread.Start(); // запускаем поток for (int i = 1; i < 9; i++) < Console.WriteLine("Главный поток:"); Console.WriteLine(i * i); Thread.Sleep(300); >Console.ReadLine(); > public static void Count() < for (int i = 1; i < 9; i++) < Console.WriteLine("Второй поток:"); Console.WriteLine(i * i); Thread.Sleep(400); >> >

Новый поток будет производить действия, определенные в методе Count. Для запуска этого метода в качестве второго потока, создается объект потока: Thread myThread = new Thread(new ThreadStart(Count)); . В конструктор передается делегат ThreadStart , который в качестве параметра принимает метод Count. И следующим методом myThread.Start() запускается поток. После этого управление передается главному потоку, и выполняются все остальные действия, определенные в методе Main.

Существует еще одна форма создания потока: Thread myThread = new Thread(Count); Хотя в данном случае явным образом мы не используем делегат ThreadStart, но неявно он создается. Компилятор C# выводит делегат из сигнатуры метода Count и вызывает соответствующий конструктор.

Класс Task, который находится в пространстве имен System.Threading.Tasks, позволяет запускать отдельную продолжительную задачу. Она запускается асинхронно в одном из потоков из пула потоков, но ее можно запускать и синхронно.

Первый способ запуска — это создание объекта Task и вызов у него метода Start:

Task task = new Task(() => Console.WriteLine("Hello Task!")); task.Start();

В качестве параметра объект Task принимает делегат Action. А метод Start() запускает задачу.

Второй способ — это использование статического метода Task.Factory.StartNew(). Он в качестве параметра принимает делегат Action. При этом этот метод сразу же запускает задачу:

Task task = Task.Factory.StartNew(() => Console.WriteLine("Hello Task!"));

В качестве результата метод возвращает запущенную задачу.

Третий способ определения и запуска задач представляет использование статического метода Task.Run():

Task task = Task.Run(() => Console.WriteLine(«Hello Task!»));

Метод Task.Run() также в качестве параметра может принимать делегат Action и возвращает объект Task.

using System; using System.Threading.Tasks; namespace HelloApp < class Program < static void Main(string[] args) < Task task1 = new Task(() =>Console.WriteLine("Task1 is executed")); task1.Start(); Task task2 = Task.Factory.StartNew(() => Console.WriteLine("Task2 is executed")); Task task3 = Task.Run(() => Console.WriteLine("Task3 is executed")); Console.ReadLine(); > > >

Вопрос 51

Что такое интеграционные тесты и unit-тесты?

Ответ:

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

Вопрос 52

Ответ: Паттерн MVVM (Model-View-ViewModel) позволяет отделить логику приложения от визуальной части. Он является архитектурным, (задает общую архитектуру приложения).

Паттерн был представлен Джоном Госсманом в 2005 году как модификация шаблона Presentation Model и был первоначально нацелен на разработку приложений в WPF. И хотя сейчас данный паттерн вышел за пределы WPF и применяется в самых различных технологиях, в том числе при разработке под Android, iOS, тем не менее WPF является довольно показательной технологией, которая раскрывает возможности данного паттерна.

MVVM состоит из трех компонентов: модели (Model), модели представления (ViewModel) и представления (View).

Вопрос 53

Что будет выведено в результате выполнения программы?

class Program < private enum En < First = 15, Second, Third = 54 >static void Main(string[] args) < Console.WriteLine((int)En.Second); Console.Read(); >>
  1. 0
  2. 1
  3. 16
  4. Возникнет ошибка на этапе компиляции

Ответ: В результате выведется число 16 (ответ 3).

Потому, что при создании типа перечисления каждому элементу целочисленное значение, причем первый элемент будет иметь значение 0, второй — 1 и так далее. Первому элементу явно присваивается значение 15, а значит второму будет присвоено соответственно 16.

Вопрос 54

Когда использовать StringBuilder предпочтительнее, чем string:

  1. Если строка редко изменяется
  2. Если строка часто изменяется
  3. Если строка содержит спецсимволы
  4. Если строка содержит исключительно цифры

Ответ:

StringBuilder предпочтительнее использовать если строка часто изменяется (ответ 2).

А в более развернутом варианте можно ответить так:

Microsoft рекомендует использовать класс String в следующих случаях:

  • При небольшом количестве операций и изменений над строками
  • При выполнении фиксированного количества операций объединения. В этом случае компилятор может объединить все операции объединения в одну
  • Когда надо выполнять масштабные операции поиска при построении строки, например IndexOf или StartsWith. Класс StringBuilder не имеет подобных методов.

Класс StringBuilder рекомендуется использовать в следующих случаях:

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

Вопрос 55

Что будет выведено в результате выполнения программы?

class Program < static void Main(string[] args) < int c = 3; Console.Write(Sum(5,3,out c)+" "); Console.Write(c); Console.ReadLine(); >static int Sum(int a, int b, out int c) < return a + b; >>
  1. 8
  2. 8 3
  3. 8 0
  4. Возникнет ошибка на этапе компиляции

Ответ: Возникнет ошибка на этапе компиляции. (ответ 4) Это произойдет в следствии того, что параметру «с» метода Sum, помеченному ключевым словом out, не присвоено значение в теле метода, а это противоречит условию использования модификатора out. Ключевое слово out нужно для того, чтобы сделать параметр «выходным». Результат метода будет получен не только через return, но и через этот параметр «с».

Вопрос 56

Что будет выведено в результате выполнения программы?

class Program < static void Main(string[] args) < var a = null; a = 10; Console.WriteLine(a); Console.ReadLine(); >>
  1. 0
  2. 10
  3. Пустая строка
  4. Возникнет ошибка на этапе компиляции

Ответ: Возникнет ошибка на этапе компиляции (Ответ 4) Причина в том что нельзя присваивать значение null к неявно типизированной переменной.

Ещё больше интересной информации на нашем Telegram канале.

> К части 7 >>

Источник вопросов:

В чем разница инкапсуляции и сокрытия

В чем разница инкапсуляции и сокрытия?

Вопрос 43

Что такое частные и общие сборки?

Вопрос 44

Что такое .Net Framework?

Вопрос 45

Чем управляемый код (managed code) отличается от неуправляемого (unmanaged code)?

Вопрос 46

LINQ lazy loading, eager loading в чем разница

Вопрос 47

Можно ли запретить наследование от своего собственного класса?

Вопрос 48

Можно ли разрешить наследование класса, но запретить переопределение метода?

Вопрос 49

Определение паттерна синглтон

Вопрос 50

Thread, task, примеры использования?

Вопрос 51

Что такое интеграционные тесты и unit-тесты?

Вопрос 52

Вопрос 53

Что будет выведено в результате выполнения программы?

class Program < private enum En < First = 15, Second, Third = 54 >static void Main(string[] args) < Console.WriteLine((int)En.Second); Console.Read(); >>
  1. 0
  2. 1
  3. 16
  4. Возникнет ошибка на этапе компиляции

Вопрос 54

Когда использовать StringBuilder предпочтительнее, чем string:

  1. Если строка редко изменяется
  2. Если строка часто изменяется
  3. Если строка содержит спецсимволы
  4. Если строка содержит исключительно цифры

Вопрос 55

Что будет выведено в результате выполнения программы?

class Program < static void Main(string[] args) < int c = 3; Console.Write(Sum(5,3,out c)+" "); Console.Write(c); Console.ReadLine(); >static int Sum(int a, int b, out int c) < return a + b; >>
  1. 8
  2. 8 3
  3. 8 0
  4. Возникнет ошибка на этапе компиляции

Вопрос 56

Что будет выведено в результате выполнения программы?

class Program < static void Main(string[] args) < var a = null; a = 10; Console.WriteLine(a); Console.ReadLine(); >>
  1. 0
  2. 10
  3. Пустая строка
  4. Возникнет ошибка на этапе компиляции

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

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