Introduction
-
Attributes are implemented with a standard “template” of code
-
Remember, “attribute” is the abstract concept of some data stored in an object; “instance variable” is the way that data is actually stored
-
First, declare an instance variable for the attribute
-
Then write a “getter” method for the instance variable
-
Then write a “setter” method for the instance variable
-
With this combination of instance variable and methods, the object has an attribute that can be read (with the getter) and written (with the setter)
-
For example, this code implements a “width” attribute for the class Rectangle:
-
Note that there is a lot of repetitive or “obvious” code here:
- The name of the attribute is intended to be “width,” so you must
name the instance variable
width
, and the methodsGetWidth
andSetWidth
, repeating the name three times. - The attribute is intended to be type
int
, so you must ensure that the instance variable is typeint
, the getter has a return type ofint
, and the setter has a parameter type ofint
. Similarly, this repeats the data type three times. - You need to come up with a name for the setter’s parameter, even though it also represents the width (i.e. the new value you want to assign to the width attribute). We usually end up naming it “widthParameter” or “widthParam” or “newWidth” or “newValue.”
- The name of the attribute is intended to be “width,” so you must
name the instance variable
-
Properties are a “shorthand” way of writing this code: They implement an attribute with less repetition.
-
Note that properties are not present in every object-oriented programming language: for example, Java does not have properties.
Writing properties
-
Declare an instance variable for the attribute, like before
-
A property declaration has 3 parts:
- Header, which gives the property a name and type (very similar to variable declaration)
get
accessor, which declares the “getter” method for the propertyset
accessor, which declares the “setter” method for the property
-
Example code, implementing the “width” attribute for Rectangle (this replaces the code in the previous example):
-
Header syntax:
[public/private] [type] [name]
-
Convention (not rule) is to give the property the same name as the instance variable, but capitalized — C# is case sensitive
-
get
accessor: Starts with the keywordget
, then a method body inside a code block (between braces)get
is like a method header that always has the same name, and its other features are implied by the property’s header- Access modifier: Same as the property header’s, i.e.
public
in this example - Return type: Same as the property header’s type, i.e.
int
in this example (so imagine it sayspublic int get()
) - Body of
get
section is exactly the same as body of a “getter”: return the instance variable
-
set
accessor: Starts with the keywordset
, then a method body inside a code block- Also a method header with a fixed name, access modifier, return type, and parameter
- Access modifier: Same as the property header’s, i.e.
public
in this example - Return type: Always
void
(like a setter) - Parameter: Same type as the property header’s type, name is always
“value”. In this case that means the parameter is
int value
; imagine the method header sayspublic void set(int value)
- Body of
set
section looks just like the body of a setter: Assign the parameter to the instance variable (and the parameter is always named “value”). In this case, that meanswidth = value
Using properties
-
Properties are members of an object, just like instance variables and methods
-
Access them with the “member access” operator, aka the dot operator
- For example,
myRect.Width
will access the property we wrote, assumingmyRect
is a Rectangle
- For example,
-
A complete example (available as a complete solution), where the “length” and “width” attributes are implemented with properties:
-
Properties “act like” variables: you can assign to them and read from them
-
Reading from a property will automatically call the
get
accessor for that property- For example,
will call the
get
accessor inside theWidth
property, which in turn executesreturn width
and returns the current value of the instance variable- This is equivalent to
using the “old” Rectangle code
-
Assigning to (writing) a property will automatically call the
set
accessor for that property, with an argument equal to the right side of the=
operator- For example,
myRectangle.Width = 15;
will call theset
accessor inside theWidth
property, withvalue
equal to 15 - This is equivalent to
myRectangle.SetWidth(15);
using the “old” Rectangle code
- For example,
In More Details
-
Note that in a property,
value
is what is called a contextual keyword: it is not a reserved word in C# (it could be used as an identifier), but inside a property it refers to something special, the name of the set method parameter. -
In the following code:
The attribute
width
is called the Width’s property backing field: it holds the data assigned to the property. -
When the property’s get and set accessors are trivial (like the ones above), we can simply omit them their body completely. That is, the previous
Width
property could be implemented usingThis is called auto-properties. Note that in this case, we do not need to declare the property’s backing field (that is, no need to have
private int width;
), but cannot refer to it! -
Conversely, get and set accessor can contains arbitrarily convoluted code:
-
Note however that if the set or get accessor is not the “trivial” one, then auto-properties cannot be used and the other accessor must be specified.
- For example, in the above code, simply writing
get;
instead ofget { return length; }
would give a compilation error.
- For example, in the above code, simply writing
-
Note that properties can exist without backing field, and they can be read-only (that is, without a set accessor) or write-only (that is, without a get accessor, but this is rarer).
-
An example of read-only property is as follows:
-
-
It is possible to set a “custom default value” for properties using a property initializer, as follows:
In this case, the property’s backing field value will be -1 by default. Properties with initializer can be read-only:
-
Finally, properties can be
static
as well:Such a property can be accessed using for example
and its value can be changed, for instance by appending a
string
to it:
Properties in UML Class Diagrams
Simple Notation
-
Since properties represent (or, rather, allow to access) attributes, they go in the “attributes” box (the second box)
-
If a property will simply “get” and “set” an instance variable of the same name, you do not need to write the instance variable in the box
- No need to write both the property
Width
and the instance variablewidth
- No need to write both the property
-
Syntax:
[+/-] <<property>> [name]: [type]
-
Note that the access modifier (+ or -) is for the property, not the instance variable, so it is + if the property is
public
(which it usually is) -
Example for
Rectangle
, assuming we converted both attributes to use properties instead of getters and setters: -
We no longer need to write all those setter and getter methods, since they are “built in” to the properties
More Accurate Notation
In general, instead of writing for example
one can write
or even
The benefit of this notation is that read-only properties can easily be
integrated in the UML class diagram, by simply omitting the <<set>>
line: