Composition and delegates

Overriding methods independent of the delegate class

You can override any of the interface methods that you delegated. Using the previous example, if the canCopy method is in the delegate interface, your MyWindow class can choose to override the canCopy method to specially handle it. For example, you could trigger different code or choose whether to delegate that method call.

For example, your MyWindow class can override a method implementation using the override keyword, and calling the private variable for your delegate if desired:

override function canCopy() : boolean {
  return someCondition && _clipboardPart.canCopy();
}

Declaring delegate implementation type in the variable definition

You can declare a delegate with an explicit type for the implementation class. This is particularly valuable if any of your code accessing the delegate directly in terms of the implementation class. For example, by declaring the type explicitly, you can avoid casting before calling methods on the implementation class that you know are not defined in the interface it implements.

To declare the type directly, add the implementation type name followed by the keyword represents before the interface name. In other words, use the following syntax:

private delegate PRIVATE_VARIABLE_NAME : IMPLEMENTATION_CLASS represents INTERFACE_NAME

For example, in the following line, _clipboardPart implements the IClipboardPart interface for the ClipboardPart class:

private delegate _clipboardPart : ClipboardPart represents IClipboardPart

Using one delegate for multiple interfaces

You can use a delegate to represent multiple interfaces for the enclosing class by implementing the methods for those interfaces. Instead of providing a single interface name, specify a comma-separated list of interfaces. For example:

private delegate _employee represents ISalariedEmployee, IOfficer

You might notice that in this example the line does not specify an explicit type for _employee, which represents two different types, which in this case are interface types. You might wonder about the compile-time type of the _employee variable. Because the variable must satisfy all requirements of both types, Gosu uses a special type called a compound type. A literal of a compound type is expressed in Gosu as a list separated by the ampersand symbol (&). For example:

ISalariedEmployee & IOfficer

Typical code does not need to mention a compound type explicitly. However, remember this syntax in case you see it during debugging code that uses the delegate keyword with multiple interfaces.

See also