Apex Properties

An Apex property is similar to a variable; however, you can do additional things in your code to a property value before it is accessed or returned. Properties can be used to validate data before a change is made, to prompt an action when data is changed (such as altering the value of other member variables), or to expose data that is retrieved from some other source (such as another class).

Property definitions include one or two code blocks, representing a get accessor and a set accessor:

If a property has only a get accessor, it is considered read only. If a property has only a set accessor, it is considered write only. A property with both accessors is considered read-write.

To declare a property, use the following syntax in the body of a class:

Public class BasicClass {

   // Property declaration
   access_modifier return_type property_name {
      get {
         //Get accessor code block
      }
      set {
         //Set accessor code block
      }
   } 
}
Where:

For example, the following class defines a property named prop. The property is public. The property returns an integer data type.

public class BasicProperty {
   public integer prop {
      get { return prop; }
      set { prop = value; }
   }
}

The following code segment calls the BasicProperty class, exercising the get and set accessors:

BasicProperty bp = new BasicProperty();
bp.prop = 5;                   // Calls set accessor
System.assertEquals(5, bp.prop);   // Calls get accessor

Note the following:

Using Automatic Properties

Properties do not require additional code in their get or set accessor code blocks. Instead, you can leave get and set accessor code blocks empty to define an automatic property. Automatic properties allow you to write more compact code that is easier to debug and maintain. They can be declared as read-only, read-write, or write-only. The following example creates three automatic properties:

public class AutomaticProperty {
   public integer MyReadOnlyProp { get; }
   public double MyReadWriteProp { get; set; }
   public string MyWriteOnlyProp { set; }
}

The following code segment exercises these properties:

AutomaticProperty ap = new AutomaticProperty();
ap.MyReadOnlyProp = 5;                 // This produces a compile error: not writable
ap.MyReadWriteProp = 5;                // No error
System.assertEquals(5, ap.MyWriteOnlyProp);   // This produces a compile error: not readable

Using Static Properties

When a property is declared as static, the property's accessor methods execute in a static context. Therefore, accessors do not have access to non-static member variables defined in the class. The following example creates a class with both static and instance properties:

public class StaticProperty {
   private static integer StaticMember;
   private integer NonStaticMember;

   // The following produces a system error
   // public static integer MyBadStaticProp { return NonStaticMember; }

   public static integer MyGoodStaticProp { 
     get {return StaticMember;} 
     set { StaticMember = value; } 
   }  
   public integer MyGoodNonStaticProp { 
     get {return NonStaticMember;} 
     set { NonStaticMember = value; } 
   } 
}

The following code segment calls the static and instance properties:

StaticProperty sp = new StaticProperty();
// The following produces a system error: a static variable cannot be
// accessed through an object instance
// sp.MyGoodStaticProp = 5;

// The following does not produce an error
StaticProperty.MyGoodStaticProp = 5;

Using Access Modifiers on Property Accessors

Property accessors can be defined with their own access modifiers. If an accessor includes its own access modifier, this modifier overrides the access modifier of the property. The access modifier of an individual accessor must be more restrictive than the access modifier on the property itself. For example, if the property has been defined as public, the individual accessor cannot be defined as global. The following class definition shows additional examples:

global virtual class PropertyVisibility {
   // X is private for read and public for write
   public integer X { private get; set; }
   // Y can be globally read but only written within a class
   global integer Y { get; public set; }
   // Z can be read within the class but only subclasses can set it
   public integer Z { get; protected set; }
}