Як розвинувся OOP, щоб включити поняття "Властивості"


12

Я походив із C ++, і я збираюся виводити C # у своїй теперішній роботі, і я просто читав багато запитань і запитань про те, яка різниця між загальнодоступними полями та властивостями та всіма спинками та перевагами у варіаціях та втіленнях цього основне запитання (наприклад, ця публікація "SO" та всі пов'язані з цим питання . Усі ці питання розглядаються з точки зору практичних відмінностей, які сприймаються як належне існування системи власності, але я думаю, що було б добре підійти до цього питання з точки зору того, що розробники всіх мов, які вирішили підтримати властивості в першому місце думали (ознайомтесь зі списком у статті Вікіпедії тут). Як OOP еволюціонував із C ++ / Java, щоб поширитись на те, що стаття у Вікіпедії цікаво визначає як середнє місце між методами та даними про учасників:

"Тобто, властивості є проміжними між кодом (методами) члена та даними даних про члена (змінні екземпляри) класу, а властивості забезпечують більш високий рівень інкапсуляції, ніж публічні поля."

MSDN додає додаткову інформацію:

"Хоча властивості технічно дуже схожі на методи, вони сильно відрізняються за сценаріями їх використання. Їх слід розглядати як розумні поля. Вони мають виклик синтаксису полів та гнучкість методів".

Я хотів би знати, як було досягнуто, що цей проміжний рівень інкапсуляції виявився корисним для програмування взагалі. Я припускаю, що ця концепція не була присутня при першому втіленні мов програмування, які виражали парадигму ООП.


8
Особливістю голої мови є просто зручний синтаксичний цукор для методів геттера та сетера. Чи є глибші причини, що стоять за тлумаченням та термінологією, я не знаю.

У турі експертів з питань ОО ваш заголовок питання може бути провокуючим і може відволікати від того, що ви насправді задавали. Не те, що я вважаю себе експертом з ОО, я кілька років "користувач ОО".
Doc Brown

Це синтаксична принадність, я пропустив перехід від "методів без параметрів" в Python до C ++. BMI = bob.weight/sq(bob.height)читається приємніше без ()ІМО.
OJFord

Я думаю, що властивості були в оригінальному (не .net) Visual Basic, як спосіб налаштування об'єкта Active X (COM). Сітка властивостей у цьому інструменті, ймовірно, мала щось спільне з прийняттям властивостей у мовах. Зауважте, що оригінальний Visual Basic багато в чому не був орієнтований на об'єкти, але він мав можливість створювати щось на кшталт класів.
Френк Хілеман

Продовження: вікно властивості було способом налаштування об'єктів без запису коду. Це отримало назву розвитку RAD. Це посилання містить скріншот вікна властивостей VB6: microsoft.com/mspress/books/WW/sampchap/4068.aspx
Френк Хілеман

Відповіді:


5

Вся справа в інкапсуляції та єдиному принципі доступу.

Об'єкт повинен бути в змозі відповісти на повідомлення, повертаючи наявні дані або використовуючи метод, але відправник не повинен бути в змозі сказати, що це таке. Або якщо ви бачите це з боку відправника: відправник повинен мати доступ до наявних даних або запустити метод через єдиний інтерфейс.

Є кілька способів цього досягти:

  • позбудьтесь даних взагалі, достатньо методів (Newspeak робить це)

    • менш радикальна форма вищезазначеного: позбудьтеся даних у відкритому інтерфейсі , тобто зробіть дані завжди приватними, у загальнодоступному інтерфейсі лише викрийте методи (Smalltalk, Ruby роблять це)
  • позбудься методів взагалі, просто мати дані (Self робить це, "method" - це лише Methodоб'єкти, призначені змінним екземпляра; змінні екземпляра шукаються при віртуальній розсилці)

  • не робити синтаксичних чи смислових відмінностей між методами та даними (Скала робить це, доступ до поля синтаксично не відрізняється від виклику методу без списку аргументів ( foo.bar), присвоєння полю синтаксично не відрізняється від виклику спеціально названого методу ( foo.bar = baz) те саме як, foo.bar_=(baz)наприклад, виклик методу з ім'ям foo_=, і значення, доступні лише для читання, можуть бути замінені або реалізовані методом без списку параметрів (тобто val foo) в надкласові, можуть бути замінені (або abstract valреалізовані) в підкласі з методом def foo)

Однак Java не дотримується принципу єдиного доступу. У Java можна розрізнити доступ до даних та запуск методу. foo.barвідрізняється від foo.bar(). Причиною цього є те, що поля та методи семантично та синтаксично відрізняються.

C # намагається виправити це, додавши до мови властивості, в основному методи, схожі на поля. Однак виклики методів все ж виглядають і відчувають себе різними від доступу до поля та властивостей. Зараз у полях та властивостях є рівномірний доступ, але методи все ще не мають.

Отже, це насправді не вирішує проблему: ви не можете виправити два різні способи доступу до речей, додавши третій спосіб доступу до речей! Навіть якщо цей третій спосіб схожий на один із двох інших способів, у вас все одно будуть (принаймні) два різні способи. Виправити це можна лише позбувшись усіх різних способів, окрім одного, або позбувшись відмінностей.

Цілком чудово мати мову з методами, властивостями та полями, але всі три повинні мати рівномірний доступ.


1
Чому ви (та інші) вважаєте, що підтримка єдиного доступу настільки важлива? За допомогою методу ви можете надати йому параметри для зміни того, що він робить або діє. З полем або властивістю у вас немає цієї можливості, ви зазвичай просто повертаєте дані (хоча властивість може бути реалізована як запущений метод замість просто відкриття приватного поля). Це здається мені інтуїтивно зрозумілим, можливо, просто тому, що я звик до цього, але що б ви набули елегантності чи продуктивності, застосовуючи рівномірний доступ? Ви боїтеся, що ви витікаєте деталі реалізації поза класом?
Майк підтримує Моніку

1
UAP збирається залишати свободу змінювати деталі реалізації, не порушуючи загальнодоступний інтерфейс. Звичайний приклад - додавання журналів. Якщо я пропоную доступ через метод, я можу тривіально змінити внутрішню частину методу для запису в журнал. Із загальнодоступним полем я не можу додати журнал без попереднього перетворення його на метод, який порушує весь код клієнта. Якщо порушити зміни, не можна ризикувати, використання методів є обов'язковим. Властивості є оптимальним компромісом, оскільки вони є повноцінними методами, але виглядають як поля. Дотримання UAP покращує інкапсуляцію та зменшує щільне з'єднання.
амон

На це питання багато хороших відповідей, але я думаю, що цей вдарив нігтем по голові, витягнувши більш фундаментальні аспекти природи мов програмування та детально розробивши відповідну формальну концепцію UAP. Твердий
jxramos

18

Ну, я не впевнений на 100%, але, мабуть, речі, ймовірно, простіші, ніж ви очікували. У школах моделювання ОО 90-х років з’явився попит на класи моделювання з інкапсульованими атрибутами членів, і коли вони реалізуються на таких мовах, як C ++ або Java, це, як правило, призводить до коду з великою кількістю геттерів та сетерів, тому багато "шуму" код для відносно простої вимоги. Зауважте, що більшість (мабуть, усі, цього не перевіряли) мов, перелічених у вашій пов'язаній статті Вікіпедії, почали впроваджувати "властивості" об'єктів наприкінці 90-х чи пізніше.

Я думаю, це було основною причиною, чому дизайнери мови вирішили додати трохи синтаксичного цукру, щоб зменшити цей шум. І хоча властивості, безумовно, не є "основною концепцією ОО", вони принаймні мають щось спільне з орієнтацією на об'єкт. Вони не демонструють "еволюцію OOP" (як передбачається в назві вашого запитання), але вони підтримують моделювання ОО на рівні мови програмування, щоб полегшити реалізацію.


Це не має нічого спільного з об'єктно-орієнтованим програмуванням, за винятком сенсу, що властивість - це абстракція поля, а поля - частина об'єктно-орієнтованого програмування. Але властивості не потрібні для об'єктно-орієнтованого програмування, як ви правильно зазначаєте.
Френк Хілеман

2
@FrankHileman: "властивість - це абстракція поля, а поля є частиною об'єктно-орієнтованого програмування" - ну, це мені здається, що ви згодні, що концепція має принаймні щось спільне з OOP. І ось чому ти мене зневажив?
Док Браун

3
Лол. Ви можете звинуватити його? Він зісковзнувся з унітазу і вдарився головою об мийку. У будь-якому випадку ... Я завжди бачив, що властивості не є суто предметом OO. Вони допомагають при інкапсуляції, а інкапсуляція допомагає з ОО.
MetaFight

1
Га! Це досить вступ до програмістів.stackexchange для мене. Lol, набагато більш нагрітий, ніж мій еквівалентний досвід у звичайному ol stackoverflow :-p Хороший спосіб переплутати день!
jxramos


11

У вас це є назад (вид). Обчислення лямбди є настільки ж основною формальною основою для мов програмування, і це вже десятиліття. У ньому немає полів.

Для моделювання змінного стану потрібно зробити дві абстракції. Один представляє встановлення деякого стану, а інший, який отримує цей стан (Глава 13 у моїй версії TaPL для довідок). Звучить знайомо? З теоретичного походження, ОО не розвинулося, щоб мати цей матеріал. О.О. прочитала Мови програмування 101 і зробила дитину кроком вперед.

З практичної точки зору існують дві досить чіткі мотивації. Ви походите з C ++, тому що потрібно було б мати, якщо б у вас було загальнодоступне поле - скажімо ... текст у текстовому полі. Що станеться, коли ви хочете змінити дизайн так, що "щоразу, коли це текстове поле змінюється, робіть благ"? Ви можете вбити це поле, зробити функцію чи дві та підключити цю логіку, оскільки ви не можете довіряти розробникам самі називати "UpdateTextbox". Це дуже нестабільна зміна вашої програми (і, на жаль, все ще є переломною реалізацією властивостей .NET). Така поведінка є повсюдно в API Windows. Оскільки це велика справа в Microsoft, C #, ймовірно, хотів зробити це менш болісним.

Інша велика мотивація - боби Java та їхня родина. Було побудовано декілька фреймворків, щоб використовувати відображення Java для пошуку GetXта SetXз’єднання та ефективної обробки ними як сучасних властивостей. Але оскільки вони не були власне мовними конструкціями, ці рамки були крихкими та нечутливими. Якби ви ввели ім’я, все просто бідко розірветься. Якщо одного реконструювали, нічого не переміщувало з іншого боку майна. І виконувати все шаблони поля / get / set було дуже багато і нудно (навіть для Java!). Оскільки C # був розроблений значною мірою як "Java з уроками, що вивчаються", такий біль був одним із таких уроків.

Але найголовніше - концепція власності була успішною. Це легко зрозуміти, це просто у використанні. Вони значно допомагають прийняттю, і як інструмент , програмісти виявили, що властивості вирішують цілий набір проблем більш чітко, ніж будь-які функції або поля.


7
Я зголосився, здебільшого, за занадто багато посилань на нерелевантні формальні лайно. Насправді реалізація мов програмування має розглянути набагато серйозніші речі, ніж включення їх чи ні в чисельність лямбда.
DeadMG

9
@DeadMG - це, безумовно, правда, але з іншого боку, реалізатори мови програмування незмінно знайомі з цим неактуальним формальним лаєм . Думати, що це не вплинуло на їхні проекти, наївно.
Теластин

3
Це, безумовно, не "неактуальне формальне лайно". Однак обчислення лямбда, можливо, мало розглядалося для раннього мови програмування. Якщо так, процесори, ймовірно, будуть більш орієнтовані на цей менталітет.
Френк Хілеман

3
@FrankHileman - Я цілком впевнений, що
Ліпп

4
@Telastyn - так - і Лісп спочатку не повинен був бути мовою програмування, пам’ятаєте?
Френк Хілеман

3

Спеціально в .net властивості походять від старих днів Visual Basic, які, як це відбувається, не були орієнтовані на об'єкти, як ми думаємо про це сьогодні. Це було багато в чому побудовано навколо нової системи COM, яка поверхово розглядала все не обов'язково як класи, а з точки зору компонентів, які могли б відкрити властивості, доступ до яких можна отримати як у коді, так і в графічних редакторах. Коли VB і новостворений C # були об'єднані в .net, VB отримав цілу кількість функцій OOP, і вони зберегли властивості, оскільки видалення їх було б як крок назад - уявіть, якби інструмент автоматичного оновлення коду був у Visual Studio замінивши всі ваші властивості на геттери та сетери та порушуючи сумісність із усіма COM-бібліотеками. Логічно було б лише їх підтримати.


Я не думаю, що ви не повинні ігнорувати походження C #, що походить з Delphi, а раніше - Object Pascal і Turbo Pascal з об'єктами. Вони були об'єктно-орієнтованими та мали властивості (хоча я не можу пригадати, чи були у OP властивості TP5.5 чи додані вони; імовірно, вони продовжувались в C # Андерсом, тому що вони були прагматично гарною ідеєю.
amaca

Дуже цікаво, що у вас трапився єдиний, хто натрапив на складовий аспект цього питання. Щойно я додав коментар до свого питання про посилання на сайт, який перераховував властивості як частину якоїсь моделі властивості-методу-події, яку задовольняє C #. Потім я знову пошукав на сторінці свого запитання, щоб знайти "компонент", розміщуючи декілька помилкових позитивних результатів, але я думаю, що ваша відповідь фактично перегукується з тим, з чим я пов’язаний.
jxramos

3

Властивості не мають нічого спільного з об'єктно-орієнтованим програмуванням, оскільки властивості - це лише синтаксичний цукор. Властивості виглядають як поля поверхнево, і у світі .net рекомендується поводитись як поля певним чином, але вони не поля у жодному сенсі. Властивості - це синтаксичний цукор для одного або двох методів: один для отримання значення, а другий для встановлення значення. Або встановлений метод, або метод get можуть бути опущені, але не обидва. Можливо, не буде поля, що зберігає значення, повернене методом get. Оскільки вони ділять синтаксис з полями і тому, що вони часто використовують поля, люди пов'язують властивості з полями.

Властивості мають переваги перед полями:

  • У методі набору властивостей, перш ніж зберігати значення властивості, нове значення або стан об'єкта може бути перевірено набором передумов або інваріантів.
  • Метод отримання властивості може існувати для зручності, якщо отримання значення властивості логічно може вважатися еквівалентним знаходженню значення поля.
  • Метод набору властивостей може виконувати інші операції, такі як сповіщення батьківського об'єкта або прослуховування об'єктів про зміну значення властивості.

Оскільки властивості - це абстракція полів, а для синтаксичної зручності такі мови, як C #, прийняли синтаксис поля для властивостей.


2
Перший рядок зі статті Вікіпедії. "Властивість, в деяких об'єктно-орієнтованих мовах програмування, є особливим видом члена класу ...". Отже, ваше перше речення - це неправильно. А частина, що залишилася, не відповідає на питання.
Док Браун

1
@DocBrown: Цікава відповідь. Багато статей у Вікіпедії явно неправильні. Я припускаю, що ви захищаєте автора цієї конкретної статті?
Френк Хілеман

1
Не всі функції об'єктно-орієнтованих мов програмування пов'язані з об'єктно-орієнтованими поняттями.
Френк Хілеман

1
Це не змінює того факту, що ви не відповідаєте на питання.
Doc Brown

3
Слід зазначити, що необов’язково не лише сетер. Ви можете мати лише налаштування властивостей.
Теластин

2

Це питання реалізації та імплікації . Властивості були в OOP, перш ніж C ++ або Java потрапили на сцену (вони були там, з деякою шорсткістю по краях, в Simula, і вони є основними для Smalltalk). Суб'єкти з властивостями концептуально відрізняються від значень із доданим кодом. Префікси get & set у деяких мовних конвенціях служать лише для розмивання води; вони дають вам знати про різницю між полями та властивостями, припускаючи, що доступ до полів можна отримати безпосередньо без get / set таким чином, що є ідіоматичним для мови, і це проникно.

Вся суть ООП полягає в тому, щоб ставитися до речей так, ніби вони були сутністю в "реальному" світі, не так, як структури з деяким кодом, змішаним. Іншому програмісту потрібно знати дуже-дуже мало про те, як я реалізував речі, і взагалі не повинні стосуватися того, які з різних значень, які вони можуть отримати та / або встановити, є реальними, а які - віртуальними. Якщо ви переходите через мій вектор, вам не потрібно знати, чи я зберігаю кут і величину чи реальні та уявні компоненти, внутрішні для векторного об'єкта. Якщо я зміню представлення у V2.0 своєї бібліотеки, воно взагалі не повинно впливати на ваш код (хоча ви, можливо, захочете скористатись новими класними функціями). Так само є властивості, які може мати суб'єкт господарювання, які залежать від даних, що знаходяться зовні, але які є безперечно властивостями з лексичної точки зору. Ви запитуєте людей "скільки вам років", а не "будь ласка, виконайте розрахунок, який розкриє мені ваш вік", навіть якщо ви знаєте, що дані, доступні цьому "об'єкту", - це дата народження (приватний непорушний член) та сьогодні дата (загальнодоступна екологічна властивість, яка автоматично збільшується, залежно від часового поясу, літнього часу та Міжнародної лінійки дат). Вік - це властивість, а не метод, хоча для отримання туди потрібен певний розрахунок, і він не може (за винятком іграшкових комп'ютерних зображень речей із штучно обмеженим життям) зберігатись як поле. незважаючи на те, що ви знаєте, що доступними даними "об'єкта" є дата народження (приватний непорушний член) та сьогоднішня дата (публічна, приростаюча екологічна властивість, залежна від часового поясу, літнього часу та міжнародної лінійки дат ). Вік - це властивість, а не метод, хоча для отримання туди потрібен певний розрахунок, і він не може (за винятком іграшкових комп'ютерних зображень речей із штучно обмеженим життям) зберігатись як поле. незважаючи на те, що ви знаєте, що доступними даними "об'єкта" є дата народження (приватний непорушний член) та сьогоднішня дата (публічна, приростаюча екологічна властивість, залежна від часового поясу, літнього часу та міжнародної лінійки дат ). Вік - це властивість, а не метод, хоча для отримання туди потрібен певний розрахунок, і він не може (за винятком іграшкових комп'ютерних зображень речей із штучно обмеженим життям) зберігатись як поле.

Замість того, щоб думати про властивості як про підлітку дитини поля та методи, це набагато задовольняє річ методів як спеціалізований вид властивості - речі, які можуть робити ваші сутності, а не речі, якими вони є. Інакше ви концептуально не маєте справу з об'єктами / сутностями, ви маєте справу з колекціями даних, до яких, як правило, до них доданий код. У implementaions можуть бути ідентичними, але наслідки різні.

Однак не слід говорити, що ця абстракція виходить вартістю. Якщо програміст, який використовує клас, не може визначити, отримує він чи вона доступ до даних під час їх збереження або отримання / встановлення значень, які потрібно обчислити, тоді буде рівень, на якому мова також обов'язково не визначена (і тому може вимагають, щоб все вимагало проміжного коду між аксесуарами / селекторами та значеннями). Немає нічого концептуально неправильного в "структурах з кодом" - вони, безумовно, можуть бути набагато ефективнішими, - але вони просочуються впровадженням всюди, і це одна з речей, яку OOP повинен усунути.


Я згоден з деякими пунктами і НЕ згоден з іншими, але в цілому повідомленням є хорошою: Деякою інформацією про потреби об'єкта в обчислюватися , але все ще технічно інформація , яка є , а не дія , яке може бути зроблено .
Фарап

0

Зовсім нічого. Властивості та OOP не мають нічого спільного. Властивості - це не що інше, як синтаксичний цукор для функціональних викликів, і тому вони мають точно таку ж прив'язку OOP, що функція викликів do- що, скажімо, ні.

Вікіпедія, до речі, абсолютно невірна. Шаблон getMember / setMember, який ви бачите на Java, пропонує точно такі ж переваги (і недоліки), що і властивості в C #. І ви можете повторити цю схему навіть на C, якщо хочете.

Властивості в C # - це не що інше, як підтримуваний мовою синтаксичний цукор.


3
Ви коли-небудь бачили концепцію властивості в будь-якій мові програмування поза контекстом класу чи об'єкта? Я не маю.
Док Браун

1
@DocBrown: Я його реалізував. Факт полягає в тому, що властивості є досить низькими цілями для авторів мови, оскільки їх вдосконалення за допомогою звичайних функціональних викликів є низькими.
DeadMG

1
OP запитувала про історію властивостей як поняття в популярних мовах програмування. І насправді в історичному розумінні існує зв'язок між властивостями та ООП.
Док Браун

2
Можливо, мені було трохи неважливо приписувати це поняття властивостей парадигмі OOP як таке, але як концепція це, безумовно, перевершує окремі мови та їх особливості. Можливо, я намагаюся сформулювати відповідну онтологію між ними. Я не заперечую через заголовок питання, що властивості є основною ознакою / концепцією ООП, яка робить або порушує формалізм ООП, і все ж я маю сенс, що вони мають реальність лише в цьому просторі ООП, тому я поставив питання як таке .
jxramos

4
Вони не є лише синтаксичним цукром у C #, вони існують у метаданих збірки як окремі члени, і ви можете робити речі із властивостями, які ви не можете використовувати із полями, такими як прив'язка даних.
Енді
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.