![]() |
Модераторы: Partizan, gambit |
![]() ![]() ![]() |
|
Дрон |
|
||||||
![]() Java-ненавистник :) ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3179 Регистрация: 29.12.2002 Где: Санкт-Петербург Репутация: 24 Всего: 92 |
Вот в теме "Что такое C#?" тов. Domestic Cat со свойственным ему рвением ругает properties.
Дабы не разводить оффтоп, решил создать отдельную тему, чтобы окончательно разрулить ситуацию ![]() По-моему проперти для меня облегчают понимание кода, так как обычно их суть в том, чтобы по необходитмость проинициализировать/вычислить какое-либо значение и вернуть его пользователю. Мне психологически приятней писать:
чем
Так как здесь очевидно, что свойству объекта присваивается какое-то значение. Кроме того, отделение свойств от методов позволило создать такой компонент как PropertyGrid (хотя он, конечно, далёк от идеала ![]() Сейчас мне некогда, но по-позже, с радостью попытаюсь обсудить объективные преимущества и недостатки этих подходов ![]() -------------------- Да. Именно так. |
||||||
|
|||||||
arilou |
|
|||
![]() Великий МунаБудвин ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 2646 Регистрация: 15.7.2004 Где: город-герой Минск Репутация: 21 Всего: 61 |
Праально говоришь! Properties следюут принципу black-box - класс выставляет интерфейс взаимодействия с ним. Свойства:
1) Контролируют доступ к полям (раз есть поля, почему бы не быть оберткам вокруг них?) 2) Дают возможность реализовать некоторое поведение при обращении к ним, например lazy load при get, и вызов события вида "PropertyChanged" при set) |
|||
|
||||
Domestic Cat |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5452 Регистрация: 3.5.2004 Где: Dallas, US Репутация: 9 Всего: 172 |
Ну вообще то если мы следуем принципам ОО то ситуация такая
1. Инкапсуляция: Отделение интерфейса (видимых методов) от имплементации (свойств объекта, его внутренней структуры) Проще говоря, поля объектов должны мыть максимум protected, publicом могут быть только константы. 2. Программа есть набор взаимодействующих объектов. Взаимодействие осуществляется путем пересылки сообщений - посредством методов. То есть, например myObject.setColor(Colors.Black) по сути есть отсылка сообщения объекту myObject. Как и что далее будет делать с этим сообщением объект - его дело, он для остальных объектов "черный ящик". Микрософт попытался с введением свойств выделить методы, которые должны (по идее) менять какие-то свойства объекта. То есть, а.Color = Colors.Black меняет свойство объекта а, а например метод а.Resize() чего-то сделает с объектом. Почему мне это не нравицца: 1. Не всегда однозначно можно отнести метод к той или иной группе. Например, GetHashCode(). Он реализован как метод, но ведь он также может быть рассмотрен и как свойство объекта. 2. Несмотря на то, что авторы FCL, видимо, следовали описанным выше принципам, никто не мешает им НЕ следовать. Возьмем проперти Environment.CurrentDirectory. Посмотрите, что оно делает - меняет текущую рабочую директорию. Почему это не метод? Тот же Resize - почему он не проперти Size? 3. Каков выигрыш от подобного разделения на свойства и методы? Что конкретно выиграно? Усложнены язык и документация, можно писать левый код, используя проперти там, где нужен метод, и наоборот. А выигрыша то нет, поиск по докам забирает (для меня по крайней мере) больше времени. 4. Какой конкретно ОО принцип реализует подобное нововведение? По-моему оно скорее противоречит ОО принципам, поскольку у пользователя создается впечатление, что свойства объекта меняются напрямую, тогда как суть не изменилась - внутри get{} set{} по-прежнему можно делать все что угодно. Вызов метода однозначно свидетельствует об отсылке сообщения, тогда как a.Number = 2 может означать как вызов метода set_Number() так и изменения паблик поля объекта. -------------------- |
|||
|
||||
arilou |
|
|||
![]() Великий МунаБудвин ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 2646 Регистрация: 15.7.2004 Где: город-герой Минск Репутация: 21 Всего: 61 |
Domestic Cat
Мне кажется, ту штука, котрорую ты не учитываешь - это то, что свойства дают возможность реализовать поля со сложным поведением. Т.е. никто не отменяет правила того, что программист должен думать, когда применять метод, а когда - свойство. ИМХО, поля вообще не должны быть public, потому что это как раз и будет нарушением инкапсуляции (спасибо, что напомнил, как называется то, о чем я писал постом выше). Поэтому и создана отдельная сущность "свойство", которая выглядит как поле, но дает возможность определять поведение. |
|||
|
||||
Дрон |
|
|||
![]() Java-ненавистник :) ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3179 Регистрация: 29.12.2002 Где: Санкт-Петербург Репутация: 24 Всего: 92 |
По 1, 2 согласен. Только что-то я не припомню метода Resize. Проперти Size -- есть
![]() По 3 -- не знаю, меня это совсем не напрягает. По 4 -- это уже фанатизм, батенька. Чистое ООП -- это же самая мерзкая бюрократия, которую только можно придумать... Не дай Бог, так и в жизни будет ![]() ЗЫ: Я сейчас разбираюсь с X++ (Microsoft Axapta), так там вообще доступа к переменным класса извне нет! Только через методы. Причём нет разделения на гет и сет -- один метод с необязательным параметром ![]() Это сообщение отредактировал(а) Дрон - 20.6.2005, 20:18 -------------------- Да. Именно так. |
|||
|
||||
Domestic Cat |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5452 Регистрация: 3.5.2004 Где: Dallas, US Репутация: 9 Всего: 172 |
Дык я и хочу сказать, что в таком случае это выглядит как изменение поля, тогда как на самом деле это отсылка сообщения объекту, т.е. то же самое, что и метод. Добавлено @ 20:30
Это для примера было, хотя вообще-то и такое есть: http://www.bluebit.gr/NET/Library/index.as...tor-Resize.html Вот другой пример: Control.Focus() - метод. Почему он не свойство (Focus = true) ? С др. стороны: Control.Size - свойство, почему оно не метод? В чем принципиальное отличие? И Focus, и Size меняют некие характеристики объекта - его размер и наличие фокуса. -------------------- |
||||
|
|||||
AntonSaburov |
|
|||
![]() Штурман ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 5658 Регистрация: 2.7.2002 Где: Санкт-Петербург Репутация: 6 Всего: 118 |
Меня лично смущает только одно - я не вижу точно, что я делаю. Вызываю ли я метод или меняю переменную.
Если мы говорим о самой жесткой инкапсуляции, то тогда понятно по умолчанию - это просто еще одна форма записи. Но происходит вызов функции или посылка сообщения методу. Но вся штука в том, что неоднократно встречал открытые поля, которые менять хорошо бы через методы, но тем не менее их видно. Бывает, что поле вообщем-то и хорошо, что открыто. И вот тут возникает неоднозначность - все-таки что я меняю ? Проперть или просто поле. Каждый раз я должен быть внимателен и осторожен. И если проперти делались для того, чтобы в какой-то степени облегчить мою жизнь, то я как раз вижу обратное. Без пропертей все ясно и очевидно - это поле или метод. Никаких неоднозначностей. |
|||
|
||||
arilou |
|
|||
![]() Великий МунаБудвин ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 2646 Регистрация: 15.7.2004 Где: город-герой Минск Репутация: 21 Всего: 61 |
Интересная штука получается...
Ну ты же сам принимаешь решение о том, чтобы сделать свойство или метод, так? Т.е. ты чувствуешь, когда нужно одно, а когда другое? Вот например у меня. Есть реестр инстансов определенных классов. Мне нужно достать оттуда какой-нить инстанс по ключу. Я определяю индексатор (обычное свойство с параметром), и внутри него достаю нужный мне объект из hashtable. Почему свойство? Потому что 1) мне кажется, что данная операция не является посылкой сообщения классу 2) индексатор в данном случае - понятийное свойство реестра, его характеристика вида "содержимое реестра для данного ключа" (постарайтесь понять мою мысль прежде чем спорить о том, характеристика это или нет) Другой пример. У меня есть бизнес-объекты. Они ссылаются на другие бизнес-объекты. Например, есть сущность User, которая содержит ссылку на сущность Role. Role в данном случае - характеристика User, а это значит, что она реализуется в виде свойства Role, а не метода getRole(). Соответственно, если я хочу сменить роль пользователю, то я меняю его характеристику, а не посылаю ему сообщение "смени роль", это я решаю выполнить эту оперецию, а не сама сущность "пользователь". Вот если бы я хотел сделать, чтобы пользователь мог сменить роль какого-то другого пользователя, то я бы сделал метод setUserRole(user, newRole), а в нем проверял бы, может исполнитель сменить роль другого пользователя, или нет. Или более того, я бы вынес это в сервисный класс, и сделал бы метод там setUserRole(performedBy, targetUser, newRole) Вот мое видение свойств. Буду ждать комментов. |
|||
|
||||
Domestic Cat |
|
||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5452 Регистрация: 3.5.2004 Где: Dallas, US Репутация: 9 Всего: 172 |
Не понимаю. Свойство - это то же что и метод, реализация свойства в IL - это методы get_XXX, set_XXX. И в ООП ничего, кроме отсылки сообщений нет. Объясни мне разницу между Role и getRole?
Ну так нигде в ООП нет разделениай на то, что, кто и как должен делать. Ты отсылаешь сообщение - а далее ОБъЕКТ решает какие действия предпринять. И в случае с методами, и в случае со свойствами.
Давай так: каковы четкие правила, где применят; свойство, а где - метод. И объясни мне тода мои примеры насчет реализаций в FCL ![]() И какие выгоды дает это разделение. -------------------- |
||||||
|
|||||||
Domestic Cat |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5452 Регистрация: 3.5.2004 Где: Dallas, US Репутация: 9 Всего: 172 |
Кстати, ведь не всегда пользуешь код, который сам писал. Да и невозможно в любом случае упомнить все. Просто обозначения для изменения паблик полей и свойств одинаковые, а суть-то разная. -------------------- |
|||
|
||||
Дрон |
|
||||
![]() Java-ненавистник :) ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3179 Регистрация: 29.12.2002 Где: Санкт-Петербург Репутация: 24 Всего: 92 |
А какая разница? Раз мы принимаем инкапсуляцию, значит нам должно быть всё равно как класс устроен внутри. Он предоставляет нам интерфейс и мы его используем, не задумываясь, что при этом происходит.
Читать приятней ![]() role = SomeUser.Role; читается как: присвоить переменной role значение Role объекта SomeUser С методом оно читалось бы: присовить переменной роль, значение возвращаемое методом getRole, что ИМХО уже не так естественно. -------------------- Да. Именно так. |
||||
|
|||||
mr.DUDA |
|
|||
![]() 3D-маньяк ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 8244 Регистрация: 27.7.2003 Где: город-герой Минск Репутация: 110 Всего: 232 |
Domestic Cat, одна из выгод от применения пропертей состоит в том, что "свойство" воспринимается как "поле", и наоборот, т.е. я в любой момент могу заменить любое public-поле или константу класса на вычисляемое св-во, не переписывая ни строчки кода.
Ещё пример. Свойство может представлять из себя ресурс "по требованию", т.е. инициализировать и возвращать значение при первом запросе. Другой пример. Паттерн "singleton" с использованием свойств воспринимается в коде намного естественнее, чем с использованием методов: Class.Instance.DoSomething() против Class.getInstance().DoSomething(). Наконец, пиная майкрософт, нужно обратить внимание на open-source разработчиков: почему-то все поголовно используют проперти на шарпе, см. хотя бы CodeProject. -------------------- ![]() |
|||
|
||||
Domestic Cat |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5452 Регистрация: 3.5.2004 Где: Dallas, US Репутация: 9 Всего: 172 |
Обясняю позицию: myObject.methodA().methodB() расшифровывается так: Взять объект myObject и отослать ему сообщение methodA(), возвращаемому значению отослать сообщение methodB() myObject.A.methodB() Свойству объекта myObject отослать сообщение methodB(). Теперь вот такой вопрос: первая реализация через методы абсолютно абстрагируется от природы возвращаемого значения после вызова methodA. Вторая реализация фактически читается как "взять нечто, принадлежащее объекту myObject и передать ему сообщение". Заметьте, вторая ситуация ограничивает девелопера - это будет "правильно" только если A является действительно полем объекта myObject. Но ведь если например мы меняем реализацию, и теперь А хранится не как поле, а создается в методе set{} - все, проперти перестало быть свойством и должно по логике стать методом. ТЕперь, какие преимущества? 1. Удобство? Разница между Class.Instance.DoSomething() и Class.getInstance().DoSomething() - две скобки. 2. Что еще? Ну хорошо, свойство говорит мне о том, что А - это некое поле объекта. Ну и что? Собственно, мне не должно быть никакого дела, поле это, или еще что. Логика ведь не зависит от того, присваиваю я значение пропертям или вызываю методы.
Дык, мало ли что используют. Вижуал Васик 6 тоже довольно популярен ![]() -------------------- |
||||
|
|||||
mr.DUDA |
|
||||||
![]() 3D-маньяк ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 8244 Регистрация: 27.7.2003 Где: город-герой Минск Репутация: 110 Всего: 232 |
Ну почему обязательно "сообщения"?
Не "свойству объекта", а "возвращаемому свойством значению" отослать сообщение. Что же здесь "не так" ?
Неправда, те же индексаторы на том же шарпе используются ну очень редко, т.к. весч довольно специфичная, чего не скажешь о properties. Кстати, почему бы нашим уважаемым оппонентам не вспомнить о линейке продуктов Borland (CBuilder, Delphi), о языках, средах разработки, визуальных и прочих компонентах, завязанных на свойства? -------------------- ![]() |
||||||
|
|||||||
Domestic Cat |
|
||||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5452 Регистрация: 3.5.2004 Где: Dallas, US Репутация: 9 Всего: 172 |
Потому, что это принятая в ООП терминология.
"возвращаемому свойством значению" - звучит очень похоже на "возвращаемому методом значению" ![]()
Ну почему, в FCL много чего на них, особенно АДО, ДатаГрид, и пр.
Мы же не о них говорим, правильно? Да и что это доказывает? -------------------- |
||||||||
|
|||||||||
![]() ![]() ![]() |
Прежде чем создать тему, посмотрите сюда: | |
|
Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов. Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :) Так же не забывайте отмечать свой вопрос решенным, если он таковым является :) Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |