CSC/ECE 517 Fall 2011/ch1 1h hs

From Expertiza_Wiki
Jump to navigation Jump to search

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.

Syntactic Notation

There 2 common syntax for getters and setters available in programming languages:

Method Call:

value = ObjectName.getAttribute();

ObjectName.setAttribute(val); 

In the above notation a getter is the same as any other instance method call. Its common for the getters and setters to be defined as public methods.

Instance Variables:

ObjectName.Field = Value;

Value = ObjectName.Field;

In this notation getters and setters looks like a accessing a class field. In most languages, internally this would invoke a method which would behave very similar to the getter method call described above. This syntactic notation offers a convenience of using intuitive syntax of getting or setting a variable.

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++

'Getters' and 'Setters' allow you to effectively protect your data. This is a technique used greatly when creating classes in C++. The getters and setters are usually public and the variables are made private. The reason for it is the data members are not accessible outside the class. For each variable, a get method will return its value and a set method will set the value.The reason for not editing the methods directly is twofold. Firstly, if you decide that some action should be taken every time you change the value of a particular variable, you only need to edit the set method instead of looking for every place you change the variable. 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.

class A
{
  private:
  int x_value;

  public:
  // Getter
  int getx_value()
  {
      return x;
  }
  // Setter
  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

Object-oriented languages have the concept of security of data to prevent a programmer from changing an object data directly and so provide accessor methods to modify object data. Perl does not have private variables but we can still use the concept of getter, setter functions methods.

sub setName 
{
   my ( $self, $Name ) = @_;
   $self->{_Name} = $Name;
   return $self->{_Name};
}
sub getName 
{
   my( $self ) = @_;
   return $self->{_Name};
}

ColdFusion

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”.

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>



Examples from Languages that use getters and setters as instance variable references:

C#:

In C#, properties are nothing but natural extension of data fields. The properties are an important features added in language level inside C#.yC# 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 by polymorphism. They are very useful in GUI programming. The compiler generates the appropriate getter and setter methods when it parses the C# property syntax.In C#, data encapsulation is possible through either classes or structures. By using various access modifiers like private, public, protected, internal etc it is possible to control the accessibility of the class members. 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. This is a good programming practice, since the data fields are not directly accessible out side the class. We must use the set/get methods to access the data fields.


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.

Lua

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.

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 )    

Ruby

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.

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"

Php

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.

<?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;
?>

Objective C

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.

// 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


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

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.

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);
}

Scala

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”.

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

Smalltalk

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:

     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"

Actionscript

In Flex it is not usually necessary to create the wrapper getter and setting functions on an object because ActionScript supports properties. This means that you can usually just create public properties like: public var firstName:String; If the internal implementation of getting or setting the firstName property needs to change, then the class can be adapted to have getter and setter functions without changing the external interface of the class: private var _firstName:String;

Getting or setting the property would call the getter and setter functions instead of accessing the property directly

public var firstName:String;
private var _firstName:String;

public function get firstName():String {
   return _firstName;
}

public function set fullName(_firstName:String):void {
   this._firstName = _firstName;
}
// getters
var1 = obj.firstName;
var2 = obj['firstName'];
// setters
obj.firstName = "Hello World";
obj['fullName'] = "Yes";


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 getter 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. Lets use an example to explain this better. While building user interfaces, we dont want UI builder class call methods like "GetAttributes()". Classes can have methods like "DrawYourself()" and getters that returns an object that implements an interface. In our UI Construction example, GetIdentity() getter method can return an object that implements Identity Interface and this Interface includes the method "DrawYourself()". This GetIdentity() call does not return a simple field but a complex object with a defined behavior and the internals of this object is kept hidden

When to Use Getters and Setters ?

1. When a getter returns an object that implements an Interface since the interface isolates the class that uses this interface from the implementing class. 2. Generic interfaces like Java Database Connectivity (JDBC) are unaware of how it will be used and in such cases getters are used to provide flexibility

Programmers use getters and setters because of procedural language mindset. A useful design strategy to this end is to center our design in terms of use cases without getters and setters by thinking on the lines of communication or interaction between the objects with well defined behavior.

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. While such convenient mechanisms are available, it is important to use the getters and setters wisely with the goal of minimizing the data movement between the objects.

References

  • Understanding properties in C#
  • why getters and setters are evil
  • php5 OOPS tutorial
  • python-hiding attribute getters and setters behind standard attribute access
  • Object.defineProperty Function (JavaScript)
  • Getters and Setters in Scala
  • ColdFusion 9 : Implicit/Generated CFC Methods
  • Using getters and setters
  • Objective C properties
  • Smalltalk methods
  • Properties in Lua
  • Perl
  • Ruby
  • Accessors and Mutators