Инкапсуляция (видимость и "вызываемость")
От: Pek2014 Россия  
Дата: 22.05.21 10:43
Оценка:
Долго думал... оказалось что...

Если вы добавили в класс приватный метод и теперь уверены, что
никто извне класса не сможет вызвать этот новый метод (ведь он приватный!),
то вы ошибаетесь. Нет у вас такой гарантии.

Да, новый метод не будет виден никому извне класса.
Это не значит, что его невозможно вызвать извне класса.

Это разные вещи — видимость и возможность вызова ("вызываемость").

Видимость/невидимость — это то, что нам обеспечивает (гарантирует) компилятор.
А вот возможность вызова — это вопрос нашей дисциплины программирования.
Если мы будем соблюдать некоторое правило, то эти две вещи совпадут.

Правило это такое:

не отдавать вовне класса ссылки на приватные члены класса.

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

Что сплошь и рядом делается в коде WinForms. Это делает код, генерируемый Visual Studio.
Посмотрите на все методы обработки событий формы. Все эти методы — приватные,
но вызываются они не из методов класса-формы (как положено приватным методам),
а извне кода формы. Поэтому относиться к методам обработки событий формы надо
как к фактически публичным. Ведь вы не контролируете ни "как", ни "когда",
ни "почему", ни с какими аргументами вызываются эти методы!
Значит фактически это методы публичные.

Предложение: методы-обработчики событий формы надо бы делать и формально публичными,
дабы не само-обманываться... Дабы понятия "видимость" и "вызываемость"
были по возможности близкими (лучше бы совпадали).

Что думаете? Правильно я понимаю ситуацию? Ни чего не напутал (запутал)?

PS

Метод Main() программы, который по умолчанию делается приватным, мне тоже режет глаз.
Всегда его делаю публичным. Какой же он приватный, если это самый главный публичный метод,
который я выставляю наружу, чтобы операционная система исполнила мою программу?!
winforms
Re: Инкапсуляция (видимость и "вызываемость")
От: varenikAA  
Дата: 22.05.21 11:44
Оценка:
Здравствуйте, Pek2014, Вы писали:



P>Предложение: методы-обработчики событий формы надо бы делать и формально публичными,

P>дабы не само-обманываться... Дабы понятия "видимость" и "вызываемость"
P>были по возможности близкими (лучше бы совпадали).

Это ваше право, приватными поля делают, чтобы конроллировать, например процесс инициализации, а так да C# очень слабенький в этом смысле.
readonly например имеет смысл только для ссылки, в отличии от immutable в Dlang который защищает созданный объект на всю глубину графа.

PS вообще хотелось бы небольшой но конкретный пример, слова имеет свойства искажать смысл.
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re: Инкапсуляция (видимость и "вызываемость")
От: samius Япония http://sams-tricks.blogspot.com
Дата: 22.05.21 12:05
Оценка:
Здравствуйте, Pek2014, Вы писали:

P>Долго думал... оказалось что...



P>Это разные вещи — видимость и возможность вызова ("вызываемость").

Термин так себе. Он ни о чем не говорит. Вызвать можно все. Даже то, что не написано, не реализовано.
А вот видимость — это не запрет вызова, разумеется. Это такой способ обозначить интерфейс взаимодействия. Барьер абстракции, за который автор абстракции не приглашал залезать. Т.е. это всего лишь соглашение, которое при правильной реализации гарантирует корректную работу некоторого кода, если не пытаться ломать его с помощью обращения к частным полям и методам.

P>Предложение: методы-обработчики событий формы надо бы делать и формально публичными,

P>дабы не само-обманываться... Дабы понятия "видимость" и "вызываемость"
P>были по возможности близкими (лучше бы совпадали).
Нет, так делать не нужно. Это внесет путаницу, т.к. опубликованные таким образом методы обработчики будут торчать везде и провоцировать к обращению к ним, хотя они не предназначены для вызова извне формы.

P>Метод Main() программы, который по умолчанию делается приватным, мне тоже режет глаз.

P>Всегда его делаю публичным. Какой же он приватный, если это самый главный публичный метод,
P>который я выставляю наружу, чтобы операционная система исполнила мою программу?!

Исполнителю Main() виден и скрытый. Публиковать main следует лишь тогда, когда его кто-то вызывает, кроме исполнителя.

А само слово "инкапсуляция" к видимости имеет отношение лишь посредственное отношение. Буквально это "помещение в капсулу". Речь о том, что детали реализации чего-либо прячутся за барьер абстракции, пользователю отдается лишь сама абстракция, и он не нуждается в обращении к деталям. Cons/car/cdr — хороший пример инкапсуляции деталей реализации коллекции в языках, где не было модификаторов видимости. Пример того, как инкапсуляция была, а управления видимостью — нет.
Re[2]: Инкапсуляция (видимость и "вызываемость")
От: Pek2014 Россия  
Дата: 22.05.21 12:52
Оценка:
Здравствуйте, samius, Вы писали:

P>>Предложение: методы-обработчики событий формы надо бы делать и формально публичными,

P>>дабы не само-обманываться... Дабы понятия "видимость" и "вызываемость"
P>>были по возможности близкими (лучше бы совпадали).

S>Нет, так делать не нужно. ... методы обработчики не предназначены для вызова извне формы.


... для вызова кодом приложения... — да, не предназначены,
но они предназначены для вызова извне формы инфраструктурой .Net,
а значит уже не могут считаться приватными (по смыслу, фактически).

P>>Метод Main() программы, который по умолчанию делается приватным, мне тоже режет глаз.

P>>Всегда его делаю публичным. Какой же он приватный, если это самый главный публичный метод,
P>>который я выставляю наружу, чтобы операционная система исполнила мою программу?!

S>Исполнителю Main() виден и скрытый. Публиковать main следует лишь тогда, когда его кто-то вызывает, кроме исполнителя.


Зачем эти особые случаи? "кроме исполнителя"...
Предлагаю не усложнять: раз метод виден и вызывается извне, значит публичный. ИМХО.
Re: Инкапсуляция (видимость и "вызываемость")
От: fmiracle  
Дата: 22.05.21 13:18
Оценка: +3
Здравствуйте, Pek2014, Вы писали:

P>Правило это такое:

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

Но зачем?
Приватные методы нужны не для того чтобы их никто никогда не мог вызвать, а для контроля доступа — чтобы сторонний код вызывал только те методы, которые ты ему разрешил. Подписав приватный метод на событие — ты это делаешь явно сам и если уверен — то и все нормально. Тут нет неожиданного для тебя использования метода класса. И у тебя остается возможность в следующем релизе заменить подписку этого метода на любую другую — без изменения вызывающего кода.
Re[3]: Инкапсуляция (видимость и "вызываемость")
От: samius Япония http://sams-tricks.blogspot.com
Дата: 22.05.21 13:32
Оценка:
Здравствуйте, Pek2014, Вы писали:

P>Здравствуйте, samius, Вы писали:


S>>Нет, так делать не нужно. ... методы обработчики не предназначены для вызова извне формы.


P>... для вызова кодом приложения... — да, не предназначены,

P>но они предназначены для вызова извне формы инфраструктурой .Net,
P>а значит уже не могут считаться приватными (по смыслу, фактически).
Ну так же можно договориться до того, что лямбды, анонимные методы и локальные функции не могут считаться приватными. Хотя, там даже модификатор некуда приткнуть.
То, как использовать приватный метод, скарплмливать ли его инфраструктуре или нет, создавать ли подписку на событи и т.п., решает разработчик класса, а не его пользователь.

S>>Исполнителю Main() виден и скрытый. Публиковать main следует лишь тогда, когда его кто-то вызывает, кроме исполнителя.


P>Зачем эти особые случаи? "кроме исполнителя"...

P>Предлагаю не усложнять: раз метод виден и вызывается извне, значит публичный. ИМХО.

По-моему именно это и есть усложнение. В отношении main данный принцип не играет роли. Значит, избыточен.
Re[2]: Инкапсуляция (видимость и "вызываемость")
От: Pek2014 Россия  
Дата: 22.05.21 14:15
Оценка:
Здравствуйте, fmiracle, Вы писали:

F>Здравствуйте, Pek2014, Вы писали:


P>>Правило это такое:

P>>не отдавать вовне класса ссылки на приватные члены класса.
P>>Нарушить это правило легко...
P>>Например, подписав свой приватный метод на некое событие.

F>Но зачем?

F>... чтобы сторонний код вызывал только те методы, которые ты ему разрешил. ... Подписав приватный метод на событие — ты это делаешь явно сам и если уверен — то и все нормально.

Не совсем "явно", и не совсем "сам".

1. Не совсем "явно"... Хотелось бы определять, какой код предназначен для внутреннего использования,
а какой вызывается извне, не вникая в реализацию методов, а только по заголовкам методов (ориентируясь на private и public).
Автору класса лучше бы не скрывать это в глубине реализации методов, а как можно явнее об этом сказать. ИМХО

2. Не совсем "сам"... В случае WinForms, код подписки располагается среди кода, сгенерированного студией.
Программист, может не сразу осознать, что происходит у него за спиной.
Re[4]: Инкапсуляция (видимость и "вызываемость")
От: Pek2014 Россия  
Дата: 23.05.21 08:57
Оценка:
Здравствуйте, samius, Вы писали:

S>То, как использовать приватный метод, скармливать ли его инфраструктуре или нет, создавать ли подписку на событие и т.п., решает разработчик класса, а не его пользователь.


Скормить метод инфраструктуре — это открыть доступ к методу.
Разработчик класса делает это сознательно и намеренно. Имеет право.
Единственная претензия (предложение) в том, что лучше бы этот факт (факт открытия метода)
явно отразить в заголовке метода (сделать его public или лучше internal). ИМХО

— Кстати, если класс расположен в отдельной сборке, то "internal" будет почти идеальным решением:
метод и приватным не будет, и для пользователей будет закрыт.

Если класс расположен в той же сборке, что и использующий его код,
то всё равно, мне кажется, что internal будет лучше, чем private:
формальной защиты от вызова клиентским кодом не будет, но будет просьба-намёк не делать этого.

— Вот ещё аргумент в пользу internal для обработчиков событий формы — тестирование.
Приватный обработчик события не вызовешь из теста, а internal - пожалуйста...
internal winforms события
Re[5]: Инкапсуляция (видимость и "вызываемость")
От: Sinclair Россия https://github.com/evilguest/
Дата: 23.05.21 11:50
Оценка: +1
Здравствуйте, Pek2014, Вы писали:

P>Скормить метод инфраструктуре — это открыть доступ к методу.

P>Разработчик класса делает это сознательно и намеренно. Имеет право.
P>Единственная претензия (предложение) в том, что лучше бы этот факт (факт открытия метода)
P>явно отразить в заголовке метода (сделать его public или лучше internal). ИМХО
Нет. Это — плохая идея. Публичность означает, что метод может вызывать всякий, получивший ссылку на экземпляр.
А подписка на событие означает, что вызывать этот метод может только источник тех событий, на которые подписался автор обсуждаемого класса.

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


P>- Вот ещё аргумент в пользу internal для обработчиков событий формы — тестирование.

P>Приватный обработчик события не вызовешь из теста, а internal - пожалуйста...
Зачем вам вызывать обработчик события из теста напрямую?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: Инкапсуляция (видимость и "вызываемость")
От: Слава  
Дата: 23.05.21 12:09
Оценка: -2 :)
Здравствуйте, Pek2014, Вы писали:

P>- Вот ещё аргумент в пользу internal для обработчиков событий формы — тестирование.


Начнём с того, что вы в 2021 году вспоминаете про winforms.
Re[5]: Инкапсуляция (видимость и "вызываемость")
От: samius Япония http://sams-tricks.blogspot.com
Дата: 23.05.21 13:01
Оценка: +1
Здравствуйте, Pek2014, Вы писали:

P>Здравствуйте, samius, Вы писали:


S>>То, как использовать приватный метод, скармливать ли его инфраструктуре или нет, создавать ли подписку на событие и т.п., решает разработчик класса, а не его пользователь.


P>Скормить метод инфраструктуре — это открыть доступ к методу.

Нет. Доступ к методу имеет лишь тот компонент, которому скомили. Никто более не имеет доступ. Метод закрыт по прежнему и доступ к нему не равен публичному.
P>Разработчик класса делает это сознательно и намеренно. Имеет право.
P>Единственная претензия (предложение) в том, что лучше бы этот факт (факт открытия метода)
P>явно отразить в заголовке метода (сделать его public или лучше internal). ИМХО
отразить в заголовке — можно, но для чего же? А вот делать его публичным или internal — не нужно, т.к. это сделает метод публичным в полный рост. Кому от этого будет легче? Будет ли легче разработчику метода? Уверен, что нет.

P>- Кстати, если класс расположен в отдельной сборке, то "internal" будет почти идеальным решением:

P>метод и приватным не будет, и для пользователей будет закрыт.
Только не следует делать отдельную сборку для каждого класса, лишь для того, что бы его методы internal-ами размечать.

P>Если класс расположен в той же сборке, что и использующий его код,

P>то всё равно, мне кажется, что internal будет лучше, чем private:
P>формальной защиты от вызова клиентским кодом не будет, но будет просьба-намёк не делать этого.
разметка видимости не является формальной защитой от вызова. Точно не в дотнете. Она является намеком на то, что вызывать этот метод напрямую не следует. Изменение его видимости в сторону открытия (internal/public) намекает на то, что этот метод вызывать можно и нужно напрямую. Нахрена же это делать?

P>- Вот ещё аргумент в пользу internal для обработчиков событий формы — тестирование.

P>Приватный обработчик события не вызовешь из теста, а internal - пожалуйста...
Тестировать обработчики в форме — то еще занятие.
Re[6]: Инкапсуляция (видимость и "вызываемость")
От: Pek2014 Россия  
Дата: 23.05.21 13:44
Оценка:
Здравствуйте, Sinclair, Вы писали:

P>>Скормить метод инфраструктуре — это открыть доступ к методу.

P>>... лучше internal

S>Нет. Это — плохая идея. Публичность означает, что метод может вызывать всякий, получивший ссылку на экземпляр.

S>А подписка на событие означает, что вызывать этот метод может только источник тех событий, на которые подписался автор обсуждаемого класса.
S>Простая аналогия — вы дали ключ от своей квартиры другу, чтобы он мог поливать цветы во время вашего отсутствия. Это не означает, что ваша квартира теперь получила публичный доступ; ваше же предложение эквивалентно отказу от замка совсем.

Это так. Но как говорил старина Мюллер, — "Что известно двоим, то известно свинье".

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

Согласен, что вырывать замок с входной двери — это слишком. Но может быть всё-таки Мюллер прав?

Мне кажется лучший вариант — это когда класс в отдельной сборке и метод обработки события сделан internal.
Но не всегда хочется заморачиваться с отдельной сборкой и тогда уж лучше public (что чрезмерно), чем private (что не правда).

P>>- Вот ещё аргумент в пользу internal для обработчиков событий формы — тестирование.

P>>Приватный обработчик события не вызовешь из теста, а internal - пожалуйста...
S>Зачем вам вызывать обработчик события из теста напрямую?

Может так можно в тесте имитировать действия пользователя? Не уверен...
Re[6]: Инкапсуляция (видимость и "вызываемость")
От: Pek2014 Россия  
Дата: 23.05.21 14:26
Оценка:
P>>Здравствуйте, samius, Вы писали:

P>>Скормить метод инфраструктуре — это открыть доступ к методу.

S>Нет. Доступ к методу имеет лишь тот компонент, которому скомили. Никто более не имеет доступ. Метод закрыт по прежнему и доступ к нему не равен публичному.

Да. Конечно, доступ не равен публичному, но он и не равен private.
И то и другое не идеально для этой ситуации. Приходится выбирать меньшее зло.

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


P>>Разработчик класса делает это сознательно и намеренно. Имеет право.

P>>Единственная претензия (предложение) в том, что лучше бы этот факт (факт открытия метода)
P>>явно отразить в заголовке метода (сделать его public или лучше internal). ИМХО
S>отразить в заголовке — можно, но для чего же? А вот делать его публичным или internal — не нужно, т.к. это сделает метод публичным в полный рост. Кому от этого будет легче? Будет ли легче разработчику метода? Уверен, что нет.

Будет легче. Например, вы хотите запротоколировать все обращения к методам класса извне.
Получается, что вам для этого не достаточно изменить только неприватные методы. Придётся разбираться и со всеми приватными... Разве это хорошо?

P>>- Кстати, если класс расположен в отдельной сборке, то "internal" будет почти идеальным решением:

P>>метод и приватным не будет, и для пользователей будет закрыт.
S>Только не следует делать отдельную сборку для каждого класса, лишь для того, что бы его методы internal-ами размечать.

Ну конечно... Но если класс уже в отдельной сборке (по другим причинам), то это помогает делать ситуацию получше (с помощью internal).

P>>Если класс расположен в той же сборке, что и использующий его код,

P>>то всё равно, мне кажется, что internal будет лучше, чем private:
P>>формальной защиты от вызова клиентским кодом не будет, но будет просьба-намёк не делать этого.
S>разметка видимости не является формальной защитой от вызова. Точно не в дотнете. Она является намеком на то, что вызывать этот метод напрямую не следует. Изменение его видимости в сторону открытия (internal/public) намекает на то, что этот метод вызывать можно и нужно напрямую. Нахрена же это делать?

Это надо делать для того, что бы сказать программисту-пользователю класcа, что он не единственный пользователь,
что у этого класса есть несколько пользователей (несколько вызывателей):
инфраструктура .Net, другие классы, на события которых подписаны методы этого класса.
Чтобы было поменьше сюрпризов.
Re[7]: Инкапсуляция (видимость и "вызываемость")
От: Sinclair Россия https://github.com/evilguest/
Дата: 24.05.21 02:25
Оценка: +5
Здравствуйте, Pek2014, Вы писали:

P>То, что вы отдали ключ своему другу, означает, что квартирой пользуется не только хозяин.

P>Это очень важная информация о квартире и об этом хорошо бы как-то намекнуть окружающим,
P>они не обязаны изучать весь код класса, чтобы установить всех пользователей.
Нет. Вы неверно понимаете цели введения атрибутов доступа. Забудьте о том, кто кого вызывает — в конце концов, с нужным уровнем доступа через рефлексию можно вызвать и private метод.

Все эти атрибуты введены для задания контрактов.
public часть определяет внешний контракт класса — то, что он предоставляет для свободного доступа произвольному внешнему коду.
Это не разрешение "вызывать", это разрешение зависеть от.
protected определяет контракт класса по отношению к наследникам.
И так далее.

Когда вы видите метод с меткой private, это не означает, что его никто не может вызвать. Это означает, что нет никакого кода за пределами класса, который полагается на наличие в вашем классе такого метода (пренебрегая рефлексией). Это даёт вам свободу вносить в этот метод произвольные изменения. Всё.

Не надо придумывать для языка семантику, которой в нём нету. Лучше потратьте усилия на то, чтобы изучить существующую семантику.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Инкапсуляция (видимость и "вызываемость")
От: varenikAA  
Дата: 24.05.21 02:34
Оценка:
Здравствуйте, Pek2014, Вы писали:
P>Компилятор никак не помогает соблюдать это правило, а нарушить его легко...
По-моему здесь ничего не нарушается.
P>Например, подписав свой приватный метод на некое событие.
Ну и как иначе выполнить код в ответ на событие?

PS неплохо было бы приводить примеры кода и условия задачи. в современном программировании стало слишком много абстракции.
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re: Инкапсуляция (видимость и "вызываемость")
От: varenikAA  
Дата: 24.05.21 05:36
Оценка:
Здравствуйте, Pek2014, Вы писали:


P>Метод Main() программы, который по умолчанию делается приватным, мне тоже режет глаз.

P>Всегда его делаю публичным. Какой же он приватный, если это самый главный публичный метод,
P>который я выставляю наружу, чтобы операционная система исполнила мою программу?!

Для компилятора это точка входа в программу. К ОС не имеет отношения.
Если вызвать Main из кода, другое дело.
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re: Инкапсуляция (видимость и "вызываемость")
От: no4  
Дата: 24.05.21 06:34
Оценка:
Здравствуйте, Pek2014, Вы писали:

P>Правило это такое:


P>не отдавать вовне класса ссылки на приватные члены класса.


...

P>Что думаете? Правильно я понимаю ситуацию? Ни чего не напутал (запутал)?


Никого не интересует вызывается ли метод извне, постольку посколько это "извне" не зависит от вызова этого метода.

Пусть ваш класс реализует обработку какого-то события — ему передают например, экхемпляр кнопки, а он в ответ на нажатие обязвется выводить hello, world.

Допустим там есть приватный метод sayHello который подписывают на событие.

Так как снаружа не может вызвать его напрямую, то можно поменять класс, реализовав эту функциональность как угодно: статическим методом, замыканием, методоб другого классе или еще как. То есть задача разграничения публичного интерфейса и интимных подробностей реализации выполняется.
Re: Инкапсуляция (видимость и "вызываемость")
От: sergii.p  
Дата: 24.05.21 07:41
Оценка:
Здравствуйте, Pek2014, Вы писали:

P>Долго думал... оказалось что...


ну это объект общественного договора. Думать тут особо нечего. Если компилятор позволяет поставить private, то так и надо делать. Другой программист увидит публичный метод Main и будет искать по всему коду вызовы этого метода напрямую. Потом поматюкавшись на предыдущего писателя исправит доступ на private и выкинет ваши измышления в мусорный ящик.
В общем, тут можно не рефлексировать, а плыть по течению вместе со всеми.
Re[3]: Инкапсуляция (видимость и "вызываемость")
От: alexzzzz  
Дата: 24.05.21 09:28
Оценка:
Здравствуйте, Pek2014, Вы писали:

S>>Нет, так делать не нужно. ... методы обработчики не предназначены для вызова извне формы.


P>... для вызова кодом приложения... — да, не предназначены,

P>но они предназначены для вызова извне формы инфраструктурой .Net,
P>а значит уже не могут считаться приватными (по смыслу, фактически).

Вот у меня есть приватные, личные, персональные сведения, тайны и секреты. По умолчанию их никто не знает, но узнает, если я сам расскажу. Это моё право. С приватными членами типов всё то же самое. Вполне логично.

PS
Есть ещё рефлексия — аналог паяльника — выдашь все свои тайны независимо от желания.
Отредактировано 24.05.2021 9:30 alexzzzz . Предыдущая версия .
Re[7]: Инкапсуляция (видимость и "вызываемость")
От: samius Япония http://sams-tricks.blogspot.com
Дата: 24.05.21 16:20
Оценка: +2
Здравствуйте, Pek2014, Вы писали:

P>>>Здравствуйте, samius, Вы писали:


P>>>Скормить метод инфраструктуре — это открыть доступ к методу.

S>>Нет. Доступ к методу имеет лишь тот компонент, которому скомили. Никто более не имеет доступ. Метод закрыт по прежнему и доступ к нему не равен публичному.

P>Да. Конечно, доступ не равен публичному, но он и не равен private.

Именно, что равен private, если не указан другой.

private void Private()
{
}
public void Public()
{
  Private();
}


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

P>И то и другое не идеально для этой ситуации. Приходится выбирать меньшее зло.


P>Мне кажется выдавать "ограниченно публичный" метод, за приватный — это бОльшее зло.

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

P>Хотя, согласен, могут быть разные ситуации..

P>Могу представить ситуацию, когда полное открытие метода наружу будет опаснее, чем обман о приватности метода.
Обман в том, что бы делать приватные методы публичными без веских оснований.

P>Будет легче. Например, вы хотите запротоколировать все обращения к методам класса извне.

P>Получается, что вам для этого не достаточно изменить только неприватные методы. Придётся разбираться и со всеми приватными... Разве это хорошо?
Сначала нужно разобраться, что значит "извне". Если я указал с помощью лямбды порядок сортировки некоторых структур данных, является ли это обращением к методу класса извне?
И стоит ли теперь избавляться от всех лямбд, анонимных и локальных методов, делать их все публичными? Средний LINQ запрос будет добавлять десяток публичных методов в класс, которые не будут иметь ничего общего с публичным интерфейсом. Что в этом хорошего?

P>Ну конечно... Но если класс уже в отдельной сборке (по другим причинам), то это помогает делать ситуацию получше (с помощью internal).

Класс в отдельной сборке — это экзотика. Вряд ли стоит обсуждать такое.

S>>разметка видимости не является формальной защитой от вызова. Точно не в дотнете. Она является намеком на то, что вызывать этот метод напрямую не следует. Изменение его видимости в сторону открытия (internal/public) намекает на то, что этот метод вызывать можно и нужно напрямую. Нахрена же это делать?


P>Это надо делать для того, что бы сказать программисту-пользователю класcа, что он не единственный пользователь,

P>что у этого класса есть несколько пользователей (несколько вызывателей):
P>инфраструктура .Net, другие классы, на события которых подписаны методы этого класса.
P>Чтобы было поменьше сюрпризов.
Все, что нужно знать программисту-пользователю класса — это публичный интерфейс класса. Сюрпризом будет именно то, что в публичном интерфейсе класса окажется несколько (десятков ) методов, которые должны быть приватными.
Re: Инкапсуляция (видимость и "вызываемость")
От: VladD2 Российская Империя www.nemerle.org
Дата: 26.05.21 00:47
Оценка:
Здравствуйте, Pek2014, Вы писали:

P>Что думаете? Правильно я понимаю ситуацию? Ни чего не напутал (запутал)?


Думаю, что место этому в философии, а не здесь.

Конечно контракт — это не железобетонная гарантия. В конце концов есть рефлексия и даже хаки с доступом к памяти процесса. Но это явное, осознанное и грубое нарушение контракта. Тут тот кто это делает ССЗБ. Ну а уж если речь идет о банальной ссылке на методы, то тут все нормально. Ведь давать такую ссылку или нет решает автор типа.

P>Предложение: методы-обработчики событий формы надо бы делать и формально публичными,

дабы не само-обманываться... Дабы понятия "видимость" и "вызываемость"
были по возможности близкими (лучше бы совпадали).

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

И ООП тут по сути не причем. Колбэки и функции высшего порядка стандартный строительный элемент и в не ООЯ.

Ну, а к событиям действительно нужно относиться очень острожное. Фиг бы с тем, что это возможность вызвать метод. Еще и ручка за которую удерживают ваш класс. Большая часть утечек памяти в дотнете связана именно с событиями. У нас даже изобрели специальный класс позволяющий этого избежать — WeakEventHandler.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Инкапсуляция (видимость и "вызываемость")
От: VladD2 Российская Империя www.nemerle.org
Дата: 26.05.21 00:51
Оценка:
Здравствуйте, Pek2014, Вы писали:

P>Программист, может не сразу осознать, что происходит у него за спиной.


Так это проблема образования программиста. Если он не понимает, что под коптом, то он может такого натворить, что проблема вызова приватного метода покажется детской шалостью.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Инкапсуляция (видимость и "вызываемость"), покаяние
От: Pek2014 Россия  
Дата: 06.06.21 09:27
Оценка: 18 (1) +1
...читал комментарии, долго думал и согласился с коллегами. Был неправ...

Когда класс сам подписывает свои приватные методы на какие-то внешние события —
это не повод делать эти приватные методы публичными,

Успокоился вот чем.

Прикол здесь в том, что класс при такой подписке всё-таки в каком-то смысле вызывает сам себя,
но вызывает "в широком смысле слова", т.е. он делает вызов не обычным (прямым) способом, а косвенно...

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

Он формулирует условия на момент времени вызова и на то, какие аргументы вызова
надо передать в метод: "вызови меня, когда пользователь нажмёт на тебя (на кнопку),
и передай в метод ссылку на себя (на эту кнопку)". Фактически это его (класса) решение,
а не кнопки — что и как делать. Кнопка — это исполнитель его (класса) воли,
она лишь выполняет его распоряжение. Решение о вызове принимает класс-подписчик.

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

Поэтому метод оставляем приватным...

Всем спасибо.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.