Форум программистов, компьютерный форум, киберфорум
Наши страницы
C# для начинающих
Войти
Регистрация
Восстановить пароль
 
 
titan4ik
104 / 82 / 19
Регистрация: 08.01.2017
Сообщений: 495
#1

Инкапсуляция с использованием свойств. Простая непонятка №1 - C#

30.01.2017, 02:16. Просмотров 527. Ответов 21
Метки нет (Все метки)

Общеизвестно, что свойства призваны обеспечивать инкапсуляцию внутренних переменных (полей) класса и определять порядок доступа к ним извне. Но если определены и get и set как public, то, из любой точки программы можно и получить значения этих полей и присвоить им новые значения - через свойства. Так в чем в данном случае именно инкапсуляция, если полный доступ извне к полям (через свойства) всё-равно есть?
То, что в свойствах можно реализовать доп логику - это понятно и понятно, что это полезно. С инкапсуляцией - не понятно.
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
30.01.2017, 02:16
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Инкапсуляция с использованием свойств. Простая непонятка №1 (C#):

Изменение свойств ListView с использованием ComboBox
Есть такая ситуация. К примеру на форме размещены ListView, ComboBox и Button....

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

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

Изменение CSS-свойств с использованием JavaScript
Есть кнопка, которая изменяет размер шрифта: HTML код: <a href="#"...

Простая программа с использованием интернета
Решил сделать непростой консольный чат - но нигде не могу найти руководства по...

Простая задача с использованием циклов
Здраствуйте. Не могу понять в чем суть задачи и как эту суть записать на с++....

21
Sanya_sa
Модератор
686 / 676 / 293
Регистрация: 03.02.2015
Сообщений: 4,241
Записей в блоге: 8
Завершенные тесты: 3
30.01.2017, 02:28 #2
http://www.cyberforum.ru/windows-forms/thread1907229.html
1
Fulcrum_013
Заблокирован
30.01.2017, 02:49 #3
Цитата Сообщение от titan4ik Посмотреть сообщение
Так в чем в данном случае именно инкапсуляция, если полный доступ извне к полям (через свойства) всё-равно есть?
Инкапсуляция в том что сеттер может проверить корректность и/или как либо изменить записываемые данные, или производить изменение кких либо других данных обеспечивающих логическую корректность состояния класса. Точно так же геттер может модифицировать возвращаемые данные, либо вообще вычислять их на основе каких либо полей. Пример:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class TDisplayFrequency {
private:
    unsigned Numerator = 0;
    unsigned Denominator = 1;
public:
    TDisplayFrequency(unsigned aNumerator, unsigned aDenominator=1) :Numerator(aNumerator), Denominator(aDenominator) {};
    unsigned GetRate() const{ return  Numerator / Denominator; }
    unsigned SetRate(unsigned NewRate) { 
                    Numerator = NewRate; 
                    Denominator = 1;  
                    return NewRate; 
        }
    bool operator == (const TDisplayFrequency& r)const { return Rate==r.Rate; }
    bool operator != (const TDisplayFrequency& r)const { return Rate != r.Rate; }
    bool operator <= (const TDisplayFrequency& r)const { return Rate <= r.Rate; }
    bool operator >= (const TDisplayFrequency& r)const { return Rate >= r.Rate; }
    bool operator < (const TDisplayFrequency& r)const { return Rate < r.Rate; }
    bool operator > (const TDisplayFrequency& r)const { return Rate > r.Rate; }
 
    __declspec(property(get=GetRate,put=SetRate)) unsigned Rate;
};
0
Usaga
30.01.2017, 07:01
  #4

Не по теме:

Fulcrum_013, человек, задающий подобные вопросы, в шарпе-то слабо шарит. А ты ему примеры на С++ даёшь. Нафига?

0
Fulcrum_013
30.01.2017, 07:11
  #5

Не по теме:

Цитата Сообщение от Usaga Посмотреть сообщение
Не по теме:
Fulcrum_013, человек, задающий подобные вопросы, в шарпе-то слабо шарит. А ты ему примеры на С++ даёшь. Нафига?
Что под рукой было то и кинул. Прямо из редактора IDE недописанный класс. А на шарпе под рукой по определению ничего нет. Инкапсуляция свойств при этом вопрос концептуальный от языка не зависит.

0
Usaga
30.01.2017, 07:15
  #6

Не по теме:

Fulcrum_013, согласен, что от языка не зависит. Но это не значит, что новичок будет способен понять синтаксис другого языка (или вообще понять, что это другой язык). Мог бы и в редакторе форума накидать простой пример, неужели без IDE никак?

0
Fulcrum_013
30.01.2017, 07:17
  #7

Не по теме:

Цитата Сообщение от Usaga Посмотреть сообщение
Мог бы и в редакторе форума накидать простой пример, неужели без IDE никак?
С шарпом не дружу в принципе, поэтому то что на шарпе накидаю не в IDE и без попыток компиляции может ввести в заблуждение. А тут просто прям на мониторе пример был. Синтаксис похож то практически идентично за разницей что кто геттер кто сеттер отдельно указывается.

0
TopLayer
725 / 548 / 290
Регистрация: 23.10.2016
Сообщений: 1,286
Завершенные тесты: 7
30.01.2017, 07:34 #8
Цитата Сообщение от titan4ik Посмотреть сообщение
Но если определены и get и set как public
В таком случае просто не будет никакой инкапсуляции (если не зашить её в "дополнительную логику"). Вообще странный вопрос, типа "если инкапсуляция один из основных принципов ООП, то почему когда я делаю все поля класса public, она (инкапсуляция) отсутствует?".
0
Fulcrum_013
Заблокирован
30.01.2017, 07:36 #9
Цитата Сообщение от TopLayer Посмотреть сообщение
то почему когда я делаю все поля класса public,
Вопрос был в том откуда она берется когда открытыми делают свойства а не поля
1
TopLayer
725 / 548 / 290
Регистрация: 23.10.2016
Сообщений: 1,286
Завершенные тесты: 7
30.01.2017, 08:04 #10
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Вопрос был в том откуда она берется когда открытыми делают свойства а не поля
А я понял. Просто провёл аналогию с более простыми сущностями - полями класса.

Добавлено через 24 минуты
Хотя может я и не прав. wiki
Инкапсуляция (англ. encapsulation, от лат. en capsula) — в информатике упаковка данных и функций в единый компонент.
Это, в частности, приводит к другому распространённому заблуждению — рассмотрению инкапсуляции неотрывно от сокрытия.
0
titan4ik
104 / 82 / 19
Регистрация: 08.01.2017
Сообщений: 495
30.01.2017, 13:31  [ТС] #11
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Вопрос был в том откуда она берется когда открытыми делают свойства а не поля
Да, именно так.
(а свойства, как правило, именно открытые)
Пока однозначного ответа на мой вопрос не прозвучало. Если ответ только в том, что в геттерах-сеттерах можно задать логику (для понятных целей) то - прошу это подтвердить однозначно.
Правильно ли то, если нет там логики, то разница в открытых полях и в наличии открытых свойств только в том, что логику эту вставить можно в будущем без изменения в коде внешних или внутренних блоков - то есть, это и есть реализация принципа инкапсуляции - в плане такой перспективы.
И кроме того, уже понятно, что сама по себе инкапсуляция через геттеры-сеттеры автоматически не обеспечивает защиту полей класса (имеющих открытые свойства) от их "случайного" изменения извне. Теперь вижу, что сами геттеры-сеттеры такой ПОЛНОЙ защиты в принципе не обеспечивают (даже с логикой) и смысл принципа инкапсуляции - "упаковка данных и функций в единый компонент" и удобство того, что изменения кода локализуются и не тянут за собой редактирования кода в разных местах.
А защита - частично в логике геттеров-сеттеров и частично (более) - в другой (общей) логике процесса обмена данными между блоками (классами) и логике использования данных, которую должны обеспечить мозги программиста.
0
Pikemaster
298 / 298 / 215
Регистрация: 24.09.2013
Сообщений: 769
Завершенные тесты: 4
30.01.2017, 13:51 #12
Лучший ответ Сообщение было отмечено titan4ik как решение

Решение

Цитата Сообщение от titan4ik Посмотреть сообщение
Так в чем в данном случае именно инкапсуляция, если полный доступ извне к полям (через свойства) всё-равно есть?
В случае открытых свойств роль инкапсуляции в связывании методов с данными.
В качестве данных - объявленное явно поле класса или автоматически реализуемое свойство (т.е. неявное, закрытое поле класса).
В качестве методов - явные пользовательские (в блоках get/set) или неявно определенные системой (по одному для get и set). Т.е. в любом случае свойство связывает методы с данными.
В случае с нормальными, человечески-объявленными свойствами (только для чтения/записи и другие разумные вариации) здесь уже вступает в силу и второй "принцип" инкапсуляции - ограничение доступа к данным.
1
TopLayer
725 / 548 / 290
Регистрация: 23.10.2016
Сообщений: 1,286
Завершенные тесты: 7
30.01.2017, 14:12 #13
Цитата Сообщение от titan4ik Посмотреть сообщение
Пока однозначного ответа на мой вопрос не прозвучало.
Ответ:
Цитата Сообщение от titan4ik Посмотреть сообщение
уже понятно, что сама по себе инкапсуляция через геттеры-сеттеры автоматически не обеспечивает защиту полей класса (имеющих открытые свойства) от их "случайного" изменения извне
Цитата Сообщение от titan4ik Посмотреть сообщение
Если ответ только в том, что в геттерах-сеттерах можно задать логику (для понятных целей) то - прошу это подтвердить однозначно.
Нет, это не так. Пример:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class User
{
    public int Age { get; private set; }
    
    public User(int age)
    {
        if (age < 0) throw new ArgumentOutOfRangeException(nameof(age));
        
        Age = age;
    }
    
    public void WearOut()
    {
        Age++;
    }
}
Мы можем получить возраст пользователя, но не можем его явно задавать после создания объекта. Никакой дополнительной логики, но с полем такого не выйдет.
Цитата Сообщение от titan4ik Посмотреть сообщение
А защита - частично в логике геттеров-сеттеров и частично (более) - в другой (общей) логике процесса обмена данными между блоками (классами) и логике использования данных, которую должны обеспечить мозги программиста.
Вот как раз количество факторов, которые должны учитываться мозгами программиста, нужно как можно меньше оставлять. Например, не надеяться, что программист сам догадается не устанавливать возраст меньше нуля, а производить проверку при присвоении.
0
kolorotur
Эксперт .NET
9937 / 8323 / 2044
Регистрация: 17.09.2011
Сообщений: 14,325
30.01.2017, 14:58 #14
Цитата Сообщение от titan4ik Посмотреть сообщение
Так в чем в данном случае именно инкапсуляция, если полный доступ извне к полям (через свойства) всё-равно есть?
Суть в семантике.
С помощью класса вы моделируете некий объект. У любого объекта есть свойства и действия, которые с ним можно произвести.
Свойства объекта моделируются свойствами класса.
Действия над объектом моделируются методами класса.

А поля — это всего лишь механизмы, через которые реализуются свойства.

На деле множество других механизмов работает только со свойствами, а не с полями. Например, привязка данных и некоторые сериализаторы.
Кроме того, замена поля на свойство является т.н. breaking change — после замены поля на свойство (например, если вам вдруг понадобилась валидация данных на вход) перестает работать весь остальной код, который пользовался вашим классом. Чтобы он заработал вновь, его надо будет перекомпилировать.

Так что когда описываете класс, делайте свойства описываемого объекта сразу свойствами, а не полями.
1
titan4ik
104 / 82 / 19
Регистрация: 08.01.2017
Сообщений: 495
30.01.2017, 15:06  [ТС] #15
Цитата Сообщение от TopLayer Посмотреть сообщение
Мы можем получить возраст пользователя, но не можем его явно задавать после создания объекта
Ага, вы предвосхитили вопрос об автоматически задаваемых свойствах (когда поля явно не создаются и никакой спец логики не прописывается). Этот пример как раз иллюстрирует возможный вариант их полезного использования.
Насколько я понимаю, сейчас (в C# 6.0) запись
Код
public int Age { get; private set; }
допускается сводить к эквивалентной краткой:
Код
public int Age { get;}
То есть в совокупности с конструктором это может давать полезный результат. Понятно.

Добавлено через 3 минуты
Цитата Сообщение от Pikemaster Посмотреть сообщение
В случае открытых свойств роль инкапсуляции в связывании методов с данными.
Цитата Сообщение от Pikemaster Посмотреть сообщение
В случае с нормальными, человечески-объявленными свойствами (только для чтения/записи и другие разумные вариации) здесь уже вступает в силу и второй "принцип" инкапсуляции - ограничение доступа к данным.
Спасибо, понятно.

Добавлено через 1 минуту
Цитата Сообщение от kolorotur Посмотреть сообщение
Так что когда описываете класс, делайте свойства описываемого объекта сразу свойствами, а не полями.
Спасибо.
0
TopLayer
725 / 548 / 290
Регистрация: 23.10.2016
Сообщений: 1,286
Завершенные тесты: 7
30.01.2017, 15:12 #16
Цитата Сообщение от titan4ik Посмотреть сообщение
допускается сводить к эквивалентной краткой
Это не эквивалент. private set допускает присвоение из любого метода класса, а не только из конструктора.
1
titan4ik
104 / 82 / 19
Регистрация: 08.01.2017
Сообщений: 495
30.01.2017, 15:18  [ТС] #17
Информации, наверное, получено достаточно, всем спасибо, буду осмыслять.

Добавлено через 4 минуты
Цитата Сообщение от TopLayer Посмотреть сообщение
Это не эквивалент. private set допускает присвоение из любого метода класса, а не только из конструктора.
А в случае
C#
1
public int Age { get;}
Age только из конструктора можно задать?
Странно, тут об этом ни слова не было - http://metanit.com/sharp/tutorial/3.4.php
0
kolorotur
Эксперт .NET
9937 / 8323 / 2044
Регистрация: 17.09.2011
Сообщений: 14,325
30.01.2017, 17:20 #18
Цитата Сообщение от titan4ik Посмотреть сообщение
Странно, тут об этом ни слова не было
Тут есть один важный момент: в версиях языка, меньших шестой, наличие в свойстве только геттера означает, что значение ему присвоить нельзя вообще — геттер должен быть явно реализован и либо возвращать высчитываемое значение, либо возвращать поле — как в примере по ссылке. Наличие просто автореализованного геттера приведет к ошибке компиляции.
Начиная с шестой версии, наличие только автореализованного геттера означает, что свойству можно присвоить значение ровно один раз: либо в конструкторе, либо в инициализаторе.

Скорее всего, в статье по ссылке говорится о более ранних версиях языка.
1
titan4ik
104 / 82 / 19
Регистрация: 08.01.2017
Сообщений: 495
30.01.2017, 17:31  [ТС] #19
Цитата Сообщение от kolorotur Посмотреть сообщение
Начиная с шестой версии, наличие только автореализованного геттера означает, что свойству можно присвоить значение ровно один раз: либо в конструкторе, либо в инициализаторе.
Скорее всего, в статье по ссылке говорится о более ранних версиях языка.
По ссылке именно о шестой версии и именно о возможности использования одного геттера без сеттера. Но там не сказано, что присвоить можно только один раз. Спасибо. Понятно.
TopLayer, теперь понял в чем отсутствие сеттера не эквивалент private set.
0
Pikemaster
298 / 298 / 215
Регистрация: 24.09.2013
Сообщений: 769
Завершенные тесты: 4
30.01.2017, 17:40 #20
Цитата Сообщение от titan4ik Посмотреть сообщение
Но там не сказано, что присвоить можно только один раз.
Каждый вызов конструктора или инициализатора это создание нового объекта.
Т.е. для каждого объекта такому свойству можно присвоить значение только один раз. Логика же
0
30.01.2017, 17:40
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
30.01.2017, 17:40
Привет! Вот еще темы с решениями:

Простая программа с использованием потоков
Требуется в потоке сосчитать факториал 12 и вывести его значение, в результате...

Вывод некоторых свойств в DataGrid с использованием ItemsSource
Здравствуйте. Есть класс class Foo { public string Prop1 { get; set; }...

Объявление переменных с использованием свойств компонентов формы
Есть вот такой код:...

Простая тестовая программа с использованием RadioButton
Здравствуйте уважаемые форумчики! Помогите, пожалуйста, написать тестовую...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru