CSC/ECE 517 Fall 2011/ch1 1h hs
What are getters and setters ?
Object-oriented languages have the concept of security of data to prevent a programmer from changing an object data directly and so provide getter and setter methods to access/modify object data. When writing new classes, it's a good idea to pay attention to the issue of access control. Usually inside a class, we declare a data field as private and will provide a set of public SET and GET methods to access the data fields. Because of this naming convention, accessor methods are more often referred to as getter methods. This is a good programming practice, since the data fields are not directly accessible outside the class. Thus 'Getters' and 'Setters' allow us to effectively protect your data.
Advantages of getters and setters as method calls
For each variable, a get method will return its value and a set method will set the value. Here are the advantages of using getter and setter as method calls:
- Encapsulate the data from accidental / inadvertent modification. The private member variable is not part of the public interface of your class; only the public getter and setter methods are, and you are free to change their implementations without changing the public interface of your class
- If we decide that some action should be taken every time you change/access the value of a particular variable, you only need to edit the set method instead of looking for every place you change the variable. For Instance, we can keep track of how many times a variable is accessed.
- Another reason is that a person using the code can look for all methods starting with get or set instead of looking for specific variables that they need to remember.
Advantages of getters and getters as variable references(properties)
Properties are a robust way to handle object’s data. Properties support accessing the instance variables the same way as calling an instance method. A property communicates the idea of "I will make a value available to you, or accept a value from you." It's not an implementation concept, it's an interface concept. Different languages follow specific syntax for adding a property to a class. Following are the advantages properties:
- the code is much cleaner when accessing a property when compared to Java or C++ which uses 2 separate methods for each instance variable. They are very useful in GUI programming which necessitates using a lot of fields for UI elements
- With properties we have fine-grained access control. For instance we can define a property as abstract thereby forcing the derived class to define that property.
- The main advantage of using properties is that if the internal implementation of getting or setting the property needs to change, then the class can be adapted to have getter and setter functions without changing the external interface of the class. This allows the interface of the object to stay the same even if the underlying implementation of getting and setting the property changes.
Realizing the importance of getters and setters, popular IDEs like Eclipse, Visual studio has a built in mechanism to add getter and setter for a field or to create a property (in C#) for a given field.
Examples Languages that use getters and setters as method calls:
C++
class A { private: int x_value; public: // Getters int getx_value() { return x; } // Setters void setx_value( int x ) { x_value = x; } }; void main() { A a; '''a.setx_value(5)'''; cout<<'''a.getx_value()'''; }
Java
public class BookStore { String title; public String getTitle() { return title; } // a setter method might check that the value that is being assigned to the variable is legal: public void setTitle( String newTitle ) { if ( newTitle == null ) // Don't allow null strings as titles! title = "(Untitled)"; // Use an appropriate default value instead. else title = newTitle; } } public static void main() { BookStore obj; obj. setTitle(""); System.out.println(obj.getTitle()); } Output: (Untitled)
Perl
sub setName { my ( $self, $Name ) = @_; $self->{_Name} = $Name if defined($Name); return $self->{_Name}; } sub getName { my( $self ) = @_; return $self->{_Name}; } # Now Set first name using helper function. $object->setName( "ABC" ); # Get name which is set using constructor. $Name = $object->getName();
Perl does not have private variables but we can still use the concept of getter, setter functions methods.
ColdFusion
Component Person { property name property age; property city; } <!--- Once an object is created we can directly call the setters and getters for the properties as ---> <cfscript> person = new Person(); person.setName("Brad"); person.setAge(46); writeOutput("Name : #person.getName()#"); writeOutput("Age : #person.getAge()#"); </cfscript>
If we want to override the getter and setter method, you just need to define those methods in your CFC and ColdFusion will call our method instead of calling the implicit one.The implicit methods can also do some nice validation if you have given the ‘type’ for properties. For instance, if we define a property as numeric and try to provide a try to set a string as its value It will throw a nice error saying “The value cannot be converted to a numeric”.
Examples from Languages that use getters and setters as instance variable references:
C#:
class MyClass { private int x; public int X { get { return x; } set { x = value; } } } //Invocation MyClass mc = new MyClass(); mc.X = 10; // calls set accessor of the property X, and pass 10 as value of the standard field 'value'. Console.WriteLine(mc.X); // displays 10. Calls the get accessor of the property X.
C# also supports static properties, which belongs to the class rather than to the objects of the class. The properties of a Base class can be inherited to a Derived class and can be overridden polymorphicaly.
Lua
class 'Test' function Test : getLength() return # self.value end function Test : setLength(newLength) for i = self.length, newLength do table.insert(self.value, false ) end end test = Test({1, 2, 3, 4}) print(test.length) self.length = property( Test.getLength, Test.setLength )
Getter and Setter functions can be implemented in Lua, which is similar to the properties concept in C#. This allows the functions to bind to a property that can be assigned and accessed as a value.
Ruby
class Person def initialize(lname, fname) @lname = lname @fname = fname end attr_reader :lname // creates a getter method attr_writer :lname // creates a setter method attr_accessor :fname // creates both getter and setter method end x = Person.new("ABC", "XYZ") print "My name is ", x.fname, " ", x.lname, ".\n" x.fname = "PQR" print "My name is ", x.fname, " ", x.lname, ".\n"
Ruby simplifies the creation of getters and setters with a little metaprogramming and the methods attr, attr_reader, attr_writer, and attr_accessor, all from the Module class. By supplying the attr method, Ruby provides a way to acces the instances directly.
Php
<?php class Customer { public $name; private $data = array(); public function __set($dt, $vl) { $this->data[$dt] = $vl; } public function __get($dt) { return $this->data[$dt]; } } $c = new Customer(); $c->name = “Sunil”; // $name is set because its public $c->email = “email@domain.com”; //assigning email@domain.com to the $email variable. echo $c->email; ?>
An interesting aspect of php worth noting is that we can assign values to undefined variables. Because of the above limitation, PHP engine provides two magic methods __get() and __set(). __get() is used when value from an undefined variable is to be read and __set() is used when a value is to be assigned to a undefined variable of a class.In the above example when email@domain.com is assigned to the undefined variable $email, the magic method __set() is called. To this __set() method the name of the variable is passed into $dt variable of __set() method and the value i.e. email@domain.com is passed to $vl variable of the __set() method.
Objective C
// public header file @interface MyObject : NSObject { NSString *make; NSString* model; NSNumber* vin; } @property (readonly, copy) NSString *language; @property(readwrite, retain) NSString* make; @property(readwrite, retain) NSString* model; @property(readwrite, retain) NSNumber* vin; @end #import "SimpleCar.h" @implementation SimpleCar @synthesize make, model, vin; @end
In Objective C we can define a property using @property directive. @synthesize will create automatically for you a setter and a getter methods for the property which becomes accessible during the run time.
Python
class DoubleIt(object): def _get_value(self): return self._value * 2 def _set_value(self, value): self._value = value value = property(_get_value, _set_value) # Invocation x = DoubleIt() x.value = 10 print x.value x.value = 'foo' print x.value x.value = [1,2,3] print x.value
In the above python code, the output is doubled since the getter multiplies the value by 2
Javascript
function addDataProperty() { var newLine = "<br />"; var obj = {}; // Add a data property to the object. Object.defineProperty(obj, "newDataProperty", { value: 101, writable: true, enumerable: true, configurable: true }); // Set the property value. obj.newDataProperty = 102; document.write("Property value: " + obj.newDataProperty + newLine); }
Javascript supports accessing getters and setters as variable as properties. Javascript originally used __defineGetter__ and __defineSetter__ syntax to define properties which is depricated as the language evolved. Object.defineProperty is currently used for creating a property.
Scala
class Person() { // Private age variable, renamed to _age private var _age = 0 var name = "" // Getter def age = _age // Setter def age_= (value:Int):Unit = _age = value } // We can invoke the setter as follows : can invoke the setter using the following: person.age = 99
Scala has some unconventional ideas that provide a solid, well thought out, and an abbreviated syntax to access object properties. This getter code simply defines a method called “age” and returns the “_age” variable. Scala doesn’t require the return keyword. The setter method name is “age_=”. The underscore is a special character in Scala and in this case, allows for a space in the method name which essentially makes the name “age =”. The parentheses and contents dictate the value and type that needs to be passed in. The “:Unit” code is equivalent to returning void. The remaining code is setting the “_age” variable to “value”.
Smalltalk
name "gets the value of name" name:aName "sets name to the value of aName" address "gets the value of address" address:anAddress "sets anAddress to the value of anAddress"
In Smalltalk the names of getter methods are usually the same as the name of the instance variable. A colon is added to the end of setter method name e.g. colour:
Actionscript
public var fullName:String; private var _fullName:String; public function get fullName():String { return _fullName; } public function set fullName(_fullName:String):void { this._fullName = _fullName; } // getters var1 = obj.fullName; var2 = obj['fullName']; // setters obj.fullName = "Hello World"; obj['fullName'] = "Yes";
Getting or setting the property would call the getter and setter functions instead of accessing the property directly
Getters and Setters from a different perspective
A fundamental precept of OO systems is that an object should not expose any of its implementation details. This way, you can change the implementation without changing the code that uses the object. It follows then that in OO systems you should avoid getter and setter functions since they mostly provide access to implementation details. For instance if you need change the return type of a gettr method from int to long to accommodate the big numbers you need to change all the invocations of that getter method. This negates the concept of information hiding. The same issue arises when you need to change the accessed field’s type. You also have to change the getter’s return type.
Solution: Maintainability is inversely proportionate to the amount of data that moves between objects. Thus, its best to minimize data movement as much as possible. The idea is to focus on what you will do rather than how you will do it. Don't ask for the information you need to do the work; ask the object that has the information to do the work for you.
Conclusion
Getters and setters provide a convenient method to access the instance variables. A lot of new languages have come up with the support for accessing getters and setters as instance variable reference which improves the readability of the code.
References