13

I've come from a C++ background and am going all out C# in my current job and I've just been reading a lot of Q&A about what's the difference between public fields and properties and all the back and forth in variations and incarnations of this basic question (e.g. this SO post and all the related linked questions). All of those questions are addressed in terms of practical differences that take for granted the existence of a property system but I think it would be good to approach this subject in terms of what the designers of all the languages which decided to support properties in the first place were thinking (check out the list in the Wikipedia article here). How did OOP evolve from C++/Java to extend into what the Wikipedia article interestingly identifies as a middleground between methods and member data:

"That is, properties are intermediate between member code (methods) and member data (instance variables) of the class, and properties provide a higher level of encapsulation than public fields."

MSDN adds further background:

"Although properties are technically very similar to methods, they are quite different in terms of their usage scenarios. They should be seen as smart fields. They have the calling syntax of fields, and the flexibility of methods."

I'd like to know how it was arrived at that this intermediate level of encapsulation proved useful for programming in general. I'm assuming this concept was not present at the first incarnation of programming languages that expressed the OOP paradigm.

jxramos
  • 391

7 Answers7

19

Well, I am not 100% sure, but I guess things are probably simpler than you expect. From the OO modeling schools of the 90's, there was a demand for modeling classes with encapsulated member attributes, and when implemented in languages like C++ or Java, this typically lead to code with lots of getters and setters, so a lot of "noise" code for a relatively simple requirement. Note that most of (probably all, did not check this) the languages listed in your linked Wikipedia article started to introduce "properties" of objects at the end of the 90's or later.

I guess that was the main reason language designers decided to add some syntactic sugar to reduce that noise. And though properties are surely no "core OO concept", they at least have something to do with object orientation. They do not show "an evolution of OOP" (as your question title assumes), but they support OO modeling at the programming language level to make the implementation easier.

Doc Brown
  • 218,378
11

You have it backwards (kind of). Lambda Calculus exists as pretty much the core formal basis for programming languages, and has been for decades. It has no fields.

To model mutable state, you need to make two abstractions. One represents setting some state, and another that retrieves that state (Chapter 13 in my version of TaPL for reference). Sound familiar? From a theoretical background, OO didn't evolve to have this stuff. OO read Programming Languages 101 and made a baby step forward.

From a practical perspective, there are two fairly clear motivations. You come from a C++ background, so what would need to happen if you had a public field - say... the text in a textbox. What happens when you want to change your design so that "whenever this textbox changes, do blah"? You get to kill that field, make a function or two and wire up that logic, since you can not trust developers to call "UpdateTextbox" themselves. This is a very breaking change to your api (and unfortunately still a breaking change in .NET's implementation of properties). This sort of behavior is all over the place in the Windows API. Since that's a big deal at Microsoft, C# likely wanted to make that less painful.

The other big motivation is Java Beans and their kin. A number of frameworks were built to use Java reflection to look for GetX and SetX pairs and effectively treat them like modern properties. But since they weren't actual language constructs, these frameworks were fragile and unweildy. If you typo'd a name, things would just break silently. If one got refactored, nothing moved the other side of the property. And doing all of the field/get/set boilerplate was verbose and tedious (even for Java!). Since C# was developed largely as "Java with lessons learned" that sort of pain was one of those lessons.

But the biggest thing is that the property concept has been successful. It's easy to understand, it's easy to use. These help adoption greatly, and as a tool, programmers have found that properties solve a subset of problems more cleanly than either functions or fields.

Telastyn
  • 110,259
7

It's all about Encapsulation and the Uniform Access Principle.

An object should be able to respond to a message by either returning existing data or running a method, but the sender shouldn't be able to tell which is which. Or if you view this from the sender's side: the sender should be able to access existing data or run a method through a uniform interface.

There are several ways to achieve this:

  • get rid of data altogether, just have methods (Newspeak does this)

    • a less radical form of the above: get rid of data in the public interface, i.e. make data always private, in the public interface, only expose methods (Smalltalk, Ruby do this)
  • get rid of methods altogether, just have data (Self does this, "methods" are just Method objects assigned to instance variables, instance variables are looked up with virtual dispatch)

  • make no syntactic or semantic distinction between methods and data (Scala does this, accessing a field is syntactically indistinguishable from calling a method without an argument list (foo.bar), assigning to a field is syntactically indistinguishable from calling a specially named method (foo.bar = baz) is the same as foo.bar_=(baz) i.e. calling a method named foo_=, and read-only values can be overridden or implemented by a method without parameter list (i.e. val foo) in a superclass can be overridden (or an abstract val be implemented) in a subclass with a method def foo)

Java, however, doesn't follow the Uniform Access Principle. In Java, it is possible to distinguish between accessing data and running a method. foo.bar is different from foo.bar(). The reason for this is that fields and methods are semantically and syntactically distinct.

C# tries to fix this by adding properties to the language, basically methods that look like fields. However, method calls still look and feel different from field and property accesses. Fields and properties now have Uniform Access, but methods still don't.

So, this doesn't actually fix the problem: you cannot fix having two different ways to access things by adding a third way to access things! Even if that third way looks like one of the other two ways, you will still have (at least) two different ways. You can only fix it by either getting rid of all the different ways except one or get rid of the differences.

It's perfectly fine to have a language with methods, properties and fields, but all three should have uniform access.

Jörg W Mittag
  • 104,619
3

Properties have nothing to do with object-oriented programming, because properties are only syntactic sugar. Properties look like fields superficially, and in the .net world, it is recommended that they behave like fields in some ways, but they are not fields in any sense. Properties are syntactic sugar for one or two methods: one to get a value, and one to set a value. Either the set method or the get method may be omitted, but not both. There may be no field storing the value returned by the get method. Because they share a syntax with fields, and because they often use fields, people associate properties with fields.

Properties have advantages over fields:

  • In a property set method, before a property value is stored, the new value, or the state of the object, may be checked against a set of preconditions or invariants.
  • A property get method may exist for convenience, if retrieval of the property value can be logically considered equivalent to retrieval of a field value.
  • A property set method may perform other operations, such as notifying a parent object or listening objects of a change to a property value.

Because properties are the abstraction of fields, and for syntactic convenience, languages such as C# adopted the field syntax for properties.

3

In .net specifically, properties originate from the old Visual Basic days which as it happens was not object oriented in the way we think about it today. It was largely build around the then-new COM system that superficially treated everything not necessarily as classes but in terms of components which would expose properties that could be accessed both in code but also in graphical editors. When VB and the newly created C# were merged into .net, VB gained a whole lot of OOP-features and they kept properties since removing them would be like a step backwards - imagine if the automatic code update tool they had in Visual Studio had been replacing all your properties with getters and setters and was breaking compatibility with all COM-libraries. It would only be logical to support them in all .net-languages so components can be used across the whole framework without interop issues or exposing the internal implementation.

niwax
  • 139
  • 1
2

It's a matter of implementation versus implication. Properties were in OOP before C++ or Java hit the scene (they were there, with some roughness around the edges, in Simula, and they are fundamental to Smalltalk). Entities with properties are conceptually different from values with code attached. The get & set prefixes in some language conventions only serve to muddy the waters; they make you aware of the difference between fields and properties, assuming that fields may be accessed directly without get/set in a manner that is idiomatic to the language, and that's leaky.

The whole point of OOP is to treat things as if they were entities in the "real" world, not just as structs with some code mixed in. Another programmer should need to know very, very little about the way I have implemented things, and should not be at all concerned with which of the various values they are allowed to get and/or set are real and which are virtual. If you run across a vector of mine, you shouldn't need to know whether I'm storing angle and magnitude or real and imaginary components internal to the vector object. If I change the representation in V2.0 of my library, it shouldn't affect your code at all (though you may wish to take advantage of the cool new features). Similarly, there are properties an entity might have that depend on data external to the entity, but which are undoubtedly properties from a lexical standpoint. You ask people "how old are you", not "please perform the calculation that will reveal your age to me", even though you know that the data available to that "object" are date of birth (a private immutable member) and today's date (a public, auto-incrementing environmental property, dependent on time zone, daylight savings time, and the International Date Line). Age is a property, not a method, even though it takes some calculation to get there and cannot (except in toy computer representations of things with artificially-limited lifetimes) be stored as a field.

Rather than thinking of properties as the bastard child of fields and methods, it's far more satisfying to thing of methods as a specialized sort of property - things that your entities can do rather than things that they are. Otherwise you're not conceptually dealing with object/entities, you're dealing with data collections that happen to have code attached to them. The implementaions may be identical, but the implications are different.

It should be needless to say, however, that this abstraction comes at a cost. If a programmer using a class can't tell whether he or she is accessing data as it is stored or getting/setting values that need to be computed, then there will be a level at which the language is also necessarily uncertain (and therefore may require that everything requires code to intermediate between accessors/selectors and values). There is nothing conceptually wrong with "structs with code" - they can certainly be much more efficient - but they leak implementaion all over the place, and that's one of the things that OOP is supposed to eliminate.

0

Absolutely nothing whatsoever. Properties and OOP have nothing to do with each other. Properties are nothing more than syntactic sugar for function calls, and therefore have exactly the same OOP-attachment that function calls do- which is to say, none.

Wikipedia is completely incorrect, by the way. The getMember/setMember pattern you see in Java offers exactly the same advantages (and disadvantages) as properties in C#. And you can replicate this pattern even in C if you want to.

Properties in C# are nothing more than language-supported syntactic-sugar.

DeadMG
  • 36,914