More Than an Ordinary Interface

Consider an example:


	class Container #(type ContentType: type of any)
	{	enter (size: integer);
	};

	function put (content: Content; container: Container);

The above examples demonstrate interfaces for object instantiation. To create a container object, you should provide an object list that matches the interface type:
	(size: integer)
To create a put activity object (funtion call), you should provide an object list that matches the interface type:
	(content: any; container: Container)

New aspects about interfaces in Transframe include:


Parameterized Interface

It is not new if interface can be parameterized. But it is new that a paramterized interface supports dynamic binding. Let us consider an example:

    function put
	< type ContentType: any; type ContainerType: Container >
	( content: ContentType; container: ContainerType );
The function interface is parameterized by two type parameters: ContentType and ContainerType. You might thought that it was equivalent to a C++ template function or an Ada's generic function. You are right if you explicitly declare this function an inline function. But by default, a Transframe function with parameterized is called directly without inline expansion. For examples:
    put ( 24, anIntegerCollection );
    put ( book, aBookshelf );
    put ( hydrofluoricacid, anAcidContainer );
The content type and the container type are bound dynamically to the type parameters and the function put is called directly. Therefore, in the first call, ContentType is bound to integer, ContainerType is bound to IntegerCollection, content is bound to book, and container is bound to anIntegerCollection.

You are not going to worry about extensive use of parameterized interfaces that could expand your system into a giant memory-eater in other languages.

The more important thing is that you get the real polymorphism. You can provide a type which is unkonwn at compile time. For example:

    content: any = GetContentFromUserInput();
    container: Container = GetContainerFromAFactoryOnNet();
    put ( content, container );
The put function will take a correct action, responding to the actual type of the content and container. If you use C++ template function, the static expansion will take the face types of content and container, which may be abstract classes and your expansion may result in an error for calling an unimplemented virtual function.

Type Dependency

Consider the following function calls:

     put (virus, syringe);
     put (wolf, sheepfold);
Oh, let's pray that the function put is smart enough to detect all the dangers. Even the function put is smart, it is, sometimes, still too late to prevent the danger unless you crush the whole system instantly with a run-time type exception report, as it is done in Java when an array element (content) type error is detected in a array (container). Just imagine that a crimer tries to put a flame into a gas tank!

The problem is that the interface fails to establish a security door to prevent a criminal break-through. The interface:

    put (content: Content; container: Container)
can be interpreted as following:
    for any content and any container, you can do put
which is not right, and invites dangers.

Using Transframe, you can write the following interface:

    < type ContentType: any >
    ( content: ContentType; container: Container of ContentType );
or
    < type ContainerType: Container >
    ( container: ContainerType; content: ContainerType.ContentType );
which is interpreted as: or

No one can break through the interface by providing a dangerous combination.


Variable Number of Inputs

An interface can take a variable number of actual parameters. They are actually composed into a heterogeneous list and the type information is reserved there. It is not a C++ interface with a variable number of arguments where no type information is used and the convention between the caller and callee is hard-coded and error-prone. Consider an example:

    function print (object_list: PrintableObject...)
    {
	foreach (obj in object_list)
		currentDevice.print(obj.getPostscript());
    };

    print ( anImagge, aTable, aText );
You do not necessary to tell the print function how many numbers of objects and what kind of objects you are going to present. Just give a list objects, as long as they are printable objects.

You can have any number of lists declared in the interface. For example:

    function multi_print
         (  device_list: PrintingDevice...;
            object_list: PrintableObject...
         )
    {
	foreach (device in device_list) 
	   foreach (obj in object_list)
		device.print(obj.getPostscript());

    };

    multi_print ( (my_window, back_up_file),
		  (anImagge, aTable, aText)
	        );

Free-Style Operators

The formats of operators are not limited to a small set of built-in ones like infix, prefix, and postfix. They are generally defined as is in the interface specification. For examples:

     function (x: numerical) "##" (y: numerical);
defined an infix operator function, which is called in this way:
     20 ## 50.0
An operator name is always quoted, and can be separated into several sections. The format of calling looks exactly as it is declared in the interface. This way, we can create many some natural language alike expressions. Example:
    class bird is Spirit
    {   thread "flies" "to" (pos: Position) "fading" (fs: FadingStyle);
    };
Then you can have expression like:
    swan flies to horizon fading image_size and color_opacity
Another example:
    function "find"            (NamedObject...)
	     "who" "satisfies" ( function(NamedObject):boolean )
	     : NamedObject...;

    function age_limitation (NamedObject): boolean;

    volunteers := find volunteers who satisfies age_limitation;

Multiple Outputs

The both input and output of an interface are tuples. For example:

     function ObjectPairName (obj1: Object; obj2: Object): (char[], char[]);
the funtion returns a name pair.


For futher reading, check out the article: Freedom for the Right, Yet Prevention from Doing Wrong. Transframe provides safer yet more flexible programing interfaces.


[ Go back to tutorial | Tutorial home page | Transframe home page ]


More topics: