[Next] [Previous] [Up] [Top] [Contents] [Index]

2.3 Fields

2.3.2 Fields and Methods

Accessing variables solely through automatically-generated wrapper methods has a number of advantages over the traditional mechanism of direct variable access common in most object-oriented languages. Since instance variables can only be accessed through messages, all code becomes representation-independent to a certain degree. Instance variables can be overridden by methods, and vice versa, allowing code to be reused even if the representation assumed by the parent implementation is different in the child implementation. For example, in the following code, the rectangle abstraction can inherit from the polygon abstraction but alter the representation to something more appropriate for rectangles:

object polygon;
	var field vertices(@polygon);
	method draw(p@polygon, d@output_device) {
		(-- draw the polygon on an output device, accessing vertices --) }

object rectangle isa polygon;
	var field top(@rectangle);
	var field bottom(@rectangle);
	var field left(@rectangle);
	var field right(@rectangle);
	method vectices(r@rectangle) {
		-- ++ is a binary operator, here creating a new point object
		[r.top    ++ r.left,  r.top    ++ r.right,
 		 r.bottom ++ r.right, r.bottom ++ r.left] }
	method set_vertices(r@rectangle, vs) {
		(-- set corners of rectangle from vs list, if possible --) }

Even within a single abstraction, programmers can change their minds about what is stored and what is computed without rewriting lots of code. Syntactically, a simple message send that accesses an accessor method is just as concise as would be a variable access (using the p.x syntactic sugar, described in section 2.5.6), thus imposing no burden on the programmer for the extra expressiveness. Other object-oriented languages such as Self and Trellis have shown the advantages of accessing instance variables solely through special get and set accessor methods. CLOS enables get and/or set accessor methods to be defined automatically as part of the defclass form, but CLOS also provides a lower-level slot-value primitive that can read and write any slot directly. Dylan joins Self and Trellis in accessing instance variables solely through accessor methods.

An object may define or inherit several fields with the same name. Just as with overloaded methods, this is legal as long as two methods, accessor or otherwise, do not have the same name, number of arguments, and argument specializers. A method may override a field accessor method without removing the field's memory location from the object, since a resend within the overriding method may invoke the field accessor method. Implementations may optimize away the storage for a field in an object if it cannot be accessed, as with the vertices field in the rectangle object.