Я пришел из C ++ фона и полностью использую C # в своей текущей работе, и я только что прочитал много вопросов и ответов о том, в чем разница между открытыми полями и свойствами, и обо всем, что есть в вариантах и воплощениях этого основной вопрос (например, этот пост SO и все связанные вопросы ). Все эти вопросы рассматриваются с точки зрения практических различий, которые принимают как должное существование системы свойств, но я думаю, что было бы хорошо подойти к этому вопросу с точки зрения того, что разработчики всех языков, которые решили поддерживать свойства в первом место было думать (проверить список в статье в Википедии здесь). Как ООП эволюционировал от C ++ / Java, чтобы распространиться на то, что в статье в Википедии интересно идентифицируется как промежуточное звено между методами и данными-членами:
«То есть свойства являются промежуточными между кодом члена (методами) и данными члена (переменными экземпляра) класса, а свойства обеспечивают более высокий уровень инкапсуляции, чем открытые поля».
MSDN добавляет дополнительную информацию:
«Хотя свойства технически очень похожи на методы, они весьма различны с точки зрения сценариев их использования. Их следует рассматривать как интеллектуальные поля. У них есть синтаксис вызова полей и гибкость методов».
Я хотел бы знать, как получилось, что этот промежуточный уровень инкапсуляции оказался полезным для программирования в целом. Я предполагаю, что эта концепция не присутствовала при первом воплощении языков программирования, которые выражали парадигму ООП.
BMI = bob.weight/sq(bob.height)
читает лучше без()
ИМО.Ответы:
Все дело в инкапсуляции и принципе унифицированного доступа.
Объект должен иметь возможность отвечать на сообщение, возвращая существующие данные или запуская метод, но отправитель не должен иметь возможность определить, что есть что. Или, если вы просматриваете это со стороны отправителя: отправитель должен иметь доступ к существующим данным или запускать метод через единый интерфейс.
Есть несколько способов добиться этого:
избавиться от данных в целом, просто есть методы (это делает Newspeak)
избавиться от методов в целом, просто иметь данные (Self делает это, «методы» - это просто
Method
объекты, назначенные переменным экземпляра, переменные экземпляра ищутся с помощью виртуальной диспетчеризации)не делать синтаксических или семантических различий между методами и данными (Scala делает это, доступ к полю синтаксически неотличим от вызова метода без аргумента list (
foo.bar
), присваивание полю синтаксически неотличимо от вызова специально названного метода (foo.bar = baz
) - то же самое аfoo.bar_=(baz)
то есть вызов метода с именемfoo_=
, и только для чтения значения могут быть переопределены или реализованы с помощью метода без списка параметров (то естьval foo
) в суперкласс может быть переопределен (илиabstract
val
реализовать) в подклассе с методомdef foo
)Java, однако, не следует принципу унифицированного доступа. В Java можно различать доступ к данным и запуск метода.
foo.bar
отличается отfoo.bar()
. Причина этого в том, что поля и методы семантически и синтаксически различны.C # пытается исправить это, добавляя свойства в язык, в основном методы, которые выглядят как поля. Однако вызовы методов по-прежнему выглядят и отличаются от доступа к полям и свойствам. Поля и свойства теперь имеют унифицированный доступ, но методы все еще не имеют.
Таким образом, это на самом деле не решает проблему: вы не можете исправить наличие двух разных способов доступа к вещам, добавив третий способ доступа к вещам! Даже если этот третий путь выглядит как один из двух других, у вас все равно останутся (по крайней мере) два разных пути. Вы можете исправить это, либо избавившись от всех различных способов, кроме одного, либо избавившись от различий.
Прекрасно иметь язык с методами, свойствами и полями, но все три должны иметь одинаковый доступ.
источник
Ну, я не уверен на 100%, но я думаю, что все, вероятно, проще, чем вы ожидаете. В школах OO-моделирования 90-х годов существовала потребность в классах моделирования с инкапсулированными атрибутами членов, а при реализации в таких языках, как C ++ или Java, это обычно приводило к коду с большим количеством методов получения и установки, поэтому много «шума» код для относительно простого требования. Обратите внимание, что большинство (вероятно, все не проверяли это) языков, перечисленных в вашей связанной статье в Википедии, начали вводить «свойства» объектов в конце 90-х или позже.
Я предполагаю, что это было основной причиной, по которой разработчики языка решили добавить синтаксический сахар, чтобы уменьшить этот шум. И хотя свойства, безусловно, не являются «основной ОО-концепцией», они, по крайней мере, имеют отношение к ориентации объекта. Они не показывают «эволюцию ООП» (как предполагает название вашего вопроса), но они поддерживают ОО- моделирование на уровне языка программирования, чтобы упростить реализацию.
источник
У вас это задом наперед (вроде). Лямбда-исчисление существует в качестве основной формальной основы для языков программирования и существует на протяжении десятилетий. У него нет полей.
Чтобы смоделировать изменяемое состояние, вам нужно сделать две абстракции. Один представляет настройку некоторого состояния, а другой возвращает это состояние (глава 13 в моей версии TaPL для справки). Звучит знакомо? С теоретической точки зрения, у ОО не было такого материала. ОО прочитал языки программирования 101 и сделал маленький шаг вперед.
С практической точки зрения, есть две довольно четкие мотивы. Вы пришли из C ++ фона, так что бы произошло, если бы у вас было открытое поле - скажем ... текст в текстовом поле. Что происходит, когда вы хотите изменить свой дизайн так, чтобы «всякий раз, когда это текстовое поле изменялось, делал бла»? Вы можете убить это поле, создать одну или две функции и подключить эту логику, поскольку вы не можете доверять разработчикам самим вызывать «UpdateTextbox». Это очень серьезное изменение в вашем API (и, к сожалению, все еще серьезное изменение в реализации свойств .NET). Такое поведение повсеместно в Windows API. Поскольку в Microsoft это большое дело, C #, вероятно, хотел сделать это менее болезненным.
Другая большая мотивация - Java Beans и их родственники. Был создан ряд фреймворков для использования отражения Java для поиска
GetX
иSetX
сопряжения и эффективной обработки их как современных свойств. Но так как они не были реальными языковыми конструкциями, эти структуры были хрупкими и непривлекательными. Если вы напишите имя, все будет просто молча. Если один подвергся рефакторингу, ничто не переместило другую сторону собственности. И выполнение всего шаблона field / get / set было многословно и утомительно (даже для Java!). Поскольку C # разрабатывался в основном как «Java с извлеченными уроками», такой вид боли был одним из таких уроков.Но самое главное, что концепция собственности была успешной. Это легко понять, это легко использовать. Это очень помогает принятию, и, как инструмент , программисты обнаружили, что свойства решают подмножество проблем более чисто, чем функции или поля.
источник
В частности, в .net свойства берут свое начало со старых времен Visual Basic, которые, как это происходит, не были объектно-ориентированными в том виде, в каком мы думаем об этом сегодня. Она была построена вокруг новой COM-системы, которая поверхностно воспринимала все не как классы, а как компоненты, которые открывали бы свойства, к которым можно обращаться как в коде, так и в графических редакторах. Когда VB и недавно созданный C # были объединены в .net, VB приобрел множество OOP-функций и сохранили свойства, поскольку их удаление было бы шагом назад - представьте, если бы инструмент автоматического обновления кода, который они имели в Visual Studio, был заменив все ваши свойства геттерами и сеттерами и нарушив совместимость со всеми COM-библиотеками. Было бы только логично поддержать их во всем.
источник
Свойства не имеют ничего общего с объектно-ориентированным программированием, потому что свойства являются только синтаксическим сахаром. Свойства внешне выглядят как поля, и в мире .net рекомендуется, чтобы они в некотором смысле вели себя как поля, но в любом случае они не являются полями. Свойства являются синтаксическим сахаром для одного или двух методов: один для получения значения и один для установки значения. Либо метод set, либо метод get могут быть опущены, но не оба. Может не быть поля, в котором хранится значение, возвращаемое методом get. Поскольку они имеют общий синтаксис с полями и поскольку они часто используют поля, люди связывают свойства с полями.
Свойства имеют преимущества перед полями:
Поскольку свойства являются абстракцией полей, и для удобства синтаксиса такие языки, как C #, приняли синтаксис поля для свойств.
источник
Это вопрос реализации, а не последствий . Свойства были в ООП до того, как C ++ или Java появились на сцене (они были там, с некоторой шероховатостью по краям, в Simula, и они являются фундаментальными для Smalltalk). Объекты со свойствами концептуально отличаются от значений с прикрепленным кодом. Префиксы get & set в некоторых языковых соглашениях служат только для мутной воды; они сообщают вам о разнице между полями и свойствами, предполагая, что к полям можно обращаться напрямую без получения / установки таким образом, который идиоматичен для языка, и это утечка.
Весь смысл ООП состоит в том, чтобы относиться к вещам как к сущностям в «реальном» мире, а не просто как к структурам со смешанным кодом. Другой программист должен знать очень, очень мало о том, как я реализовал вещи, и не должно быть никакого отношения к тому, какие из различных значений, которые им разрешено получать и / или устанавливать, являются реальными, а какие - виртуальными. Если вы столкнетесь с моим вектором, вам не нужно будет знать, храню ли я угол и величину или реальные и мнимые компоненты, внутренние для векторного объекта. Если я изменю представление в V2.0 моей библиотеки, это вообще не должно повлиять на ваш код (хотя вы можете воспользоваться новыми замечательными функциями). Точно так же существуют свойства, которые объект может иметь, которые зависят от данных, внешних по отношению к объекту, но которые, несомненно, являются свойствами с лексической точки зрения. Вы спрашиваете людей «сколько вам лет», а не «пожалуйста, выполните расчеты, которые покажут мне ваш возраст», даже если вы знаете, что для этого «объекта» доступны данные о дате рождения (частный неизменный член) и сегодняшнем дне. дата (общедоступное, автоматически увеличивающееся свойство среды, зависящее от часового пояса, летнего времени и международной линии дат). Возраст - это свойство, а не метод, даже если для его достижения требуются некоторые вычисления, и он не может (кроме игрушечных компьютерных представлений вещей с искусственно ограниченным временем жизни) сохраняться в виде поля. даже если вы знаете, что для этого «объекта» доступны данные о дате рождения (частный неизменяемый элемент) и сегодняшней дате (общедоступное, автоматически увеличивающееся свойство среды, зависящее от часового пояса, летнего времени и международной строки даты ). Возраст - это свойство, а не метод, даже если для его достижения требуются некоторые вычисления, и он не может (кроме игрушечных компьютерных представлений вещей с искусственно ограниченным временем жизни) сохраняться в виде поля. даже если вы знаете, что для этого «объекта» доступны данные о дате рождения (частный неизменяемый элемент) и сегодняшней дате (общедоступное, автоматически увеличивающееся свойство среды, зависящее от часового пояса, летнего времени и международной строки даты ). Возраст - это свойство, а не метод, даже если для его достижения требуются некоторые вычисления, и он не может (кроме игрушечных компьютерных представлений вещей с искусственно ограниченным временем жизни) сохраняться в виде поля.
Вместо того, чтобы думать о свойствах как о внебрачных дочерних элементах полей и методов, гораздо приятнее воспринимать методы как специализированный вид собственности - вещи, которые могут делать ваши сущности, а не вещи, которыми они являются. В противном случае вы концептуально не имеете дело с объектами / сущностями, вы имеете дело с коллекциями данных, к которым прикреплен код. В implementaions могут быть идентичными, но последствия разные.
Однако не стоит говорить, что эта абстракция обходится дорого. Если программист, использующий класс, не может определить, обращается ли он или она к данным, когда они хранятся, или получает / устанавливает значения, которые необходимо вычислить, тогда будет уровень, на котором язык также обязательно будет неопределенным (и, следовательно, может требует, чтобы все требовало кода для промежуточного соединения между аксессорами / селекторами и значениями). Нет ничего концептуально неправильного в «структурах с кодом» - они, безусловно, могут быть гораздо более эффективными - но они повсеместно пропускают реализацию, и это одна из вещей, которую ООП должен устранить.
источник
Абсолютно ничего вообще. Свойства и ООП не имеют ничего общего друг с другом. Свойства являются не чем иным, как синтаксическим сахаром для вызовов функций, и, следовательно, имеют точно такое же ООП-вложение, что и вызовы функций, то есть нет.
Кстати, википедия совершенно неверна. Шаблон getMember / setMember, который вы видите в Java, предлагает те же преимущества (и недостатки), что и свойства в C #. И вы можете повторить этот шаблон даже в C, если хотите.
Свойства в C # - не более чем поддерживаемый языком синтаксический сахар.
источник