Sun’s
Java Tutorial defines an interface as having the following characteristics:
An interface
is a device that unrelated objects use to interact with each other … An
interface is probably most analogous to a protocol (an agreed on behavior) … When
a class implements an interface, the class agrees to implement all the methods
defined in the interface … You use an interface to define a protocol of
behavior that can be implemented by any class anywhere in the class hierarchy.
Interfaces are useful for the following:
·
Capturing
similarities among unrelated classes without artificially forcing a class
relationship.
·
Declaring methods
that one or more classes are expected to implement.
·
Revealing an
object's programming interface without revealing its class.
(http://java.sun.com/docs/books/tutorial/java/concepts/interface.html)
The Proteus Interface
mechanism requires that all interfaces inherit from Interface class. This class defines no properties of its own,
and is simply a marker class for interfaces. To define an interface an author
must create a class inheriting from Interface that defines the
properties required by the interface.
Suppose, for example that we
want to define an interface MyInterface, which will
define properties myProperty1, myProperty2, myProperty3:
class MyInterface: Interface
{
MY_CONSTANT_1 = 1
MY_CONSTANT_2 = 2
MY_CONSTANT_3 = 3
myProperty1() {}
myProperty2([args]) {}
myProperty3(parm) {}
}
Notice that the properties we’ve
defined consist of methods (behavior), and ALL-CAPS attributes that have
integer values. No other attributes (state) are permitted as part of an
interface definition.
We’ve also included the
method parameters, when the method requires them, as part of the definition.
Finally, all the properties have empty code blocks. An interface doesn’t do
anything, it merely defines the properties (and their parameters) that a class
must define in order to implement the interface.
Once we’ve defined an
appropriate interface for our class, we must implement it in the class. To do
this we must either first include the interface in the object’s &myInterfaces list:
Class MyClass: object
{
myInterfaces
= [MyInterface]
myProperty1()
{ return ‘hello’; }
myProperty2([args])
{ if (args.length() == 0) return ‘hello’; }
myProperty3(val)
{ return val; }
}
or define the interface as a
nested object using the proteusServiceFor() macro:
Class MyClass: object
{
proteusServiceFor(Interface)
{
myInterface:
MyInterface {}
}
myProperty1()
{ return ‘hello’; }
myProperty2([args])
{ if (args.length() == 0) return ‘hello’; }
myProperty3(val)
{ return val; }
}
or most concisely of all,
using the implements macro:
Class MyClass: object
{
implements(MyInterface)
myProperty1()
{ return ‘hello’; }
myProperty2([args])
{ if (args.length() == 0) return ‘hello’; }
myProperty3(val)
{ return val; }
}
Then we must define the
properties required by the interface in the class.
During pre-compile each
object that defines an interfaces list is checked against the interfaces in its
list to make sure that it defines the required properties and their
corresponding parameters.
Once the interface has been
defined and the object’s implementation validated by pre-compile, the
usefulness of the interface can be employed by the classes implementsIF(interface) and enforcesIF(interface) methods.
These methods are similar to ofKind() in that they
allow an author to determine if an object is appropriate for use based on the
behaviors it defines.
val = obj.implementsIF(MyIF);
returns true if the object implements or inherits the interface MyIF; otherwise it returns nil.
Similarly, the method:
obj.enforcesIF(MyIF);
doesn’t return any value, but
instead throws an exception if the obj.implementsIF(MyIF) returns nil. An object
that passes the implementsIF() method check can then be used by code that requires
the interface properties.
This file is part of the TADS 3
Proteus Library Extension
Copyright ©
2001-2004 Kevin Forchione.