overview of object methods - Maple Help

Online Help

All Products    Maple    MapleSim


Home : Support : Online Help : Programming : Objects : object/methods

Defining and Using Object Methods - overview of object methods

Methods

• 

Methods are procedures defined when declaring a Maple object.  There are a few notes for methods.

Method Names Should Be Declared static

• 

In Maple, method names should be declared as static.  In most cases, all objects of the same class use the same procedures for their methods.  Thus if the method names are not declared static, each object will have a separate copy of the procedure.  For more information on using static with objects, see Creating a New Object.

Object Must Be Passed into Methods

• 

If you declare a method that needs to access the contents of an object, that object must be passed into the method as an argument.  This is in contrast to some object oriented languages which allow access to the contents of an object associated with the current invocation, either through direct access to the object's members or through a self variable.  The method will have access to the local variables of any object of the same class that the method was declared in.

• 

In the following example, the set and toString methods expect an instance of the StringBuffer class as their first argument.

module StringBuffer()
   option object;

   local buffer := Array( 1..0, datatype=integer[1] );

   export set::static := proc( sb::StringBuffer, s::string, $ )
       sb:-buffer := Array( convert( s, ':-bytes' ), datatype=integer[1] );
       NULL;
   end;

   export toString::static := proc( sb::StringBuffer, $ )
       convert( convert(sb:-buffer,list), ':-bytes' );
   end;

   export append::static := proc( sb::StringBuffer, s::string, $ )
       local l, n;

       l := convert( s, ':-bytes' );

       n := :-numelems( sb:-buffer )+1;
       sb:-buffer( n..n+:-numelems(l)-1 ) := Array(l);
       NULL;
   end;
end:

Calling Methods

Calling an Exported Method

• 

To call a method that is exported by an object, use the standard function calling syntax with the object as an argument.  When evaluating the function call, Maple will search the arguments, left to right, for an object that exports a method with the same name as the specified function.  The first object found with a matching method will have its method called with the given arguments.

sb := Object(StringBuffer);

sb:=Object<<StringBuffer,139723741403136>>

(1)

set( sb, "Hello" );

append( sb, " " );

append( sb, "World" );

toString( sb );

Hello World

(2)

Calling a local Method

• 

Locals can only be accessed by methods defined within the object's declaration, so normal scoping rules are usually sufficient to resolve the function call to the correct procedure.

Objects in Indexed Function Calls

• 

When making an indexed function call (of the form func[index](args)) Maple will also check the indices (index) for a matching object as well as the arguments.  If a matching object is found in the indices, that object will be used before one found in the arguments.

Using ModuleCopy and ModuleApply to Create an Object Factory

• 

The special ModuleCopy and ModuleApply methods can be combined to implement an object factory routine.  The ModuleCopy method is used to define what happens when the Object routine is called to create a new object.  The ModuleApply method defines what happens when an object name is applied (that is, used as a function call).

• 

By adding the following methods to the declaration of StringBuffer,  the ModuleApply method becomes a factory routine.

export ModuleCopy::static := proc( sb::StringBuffer, proto::StringBuffer,
            s::{string,StringBuffer}, $ )
        if ( _npassed = 3 ) then
            if ( type( s, ':-string' ) ) then
                set( sb, s );
            else
                sb:-buffer := Array( s:-buffer );
                NULL;
            end;
        else
            sb:-buffer := Array( proto:-buffer );
            NULL;
        end;
    end;

export ModuleApply::static := proc( )
        Object( StringBuffer, _passed );
    end;

• 

Having defined a ModuleCopy and ModuleApply, we can now call StringBuffer like a function to create new instances.

sb2 := StringBuffer();

sb2:=Object<<StringBuffer,139723741423040>>

(3)

set( sb2, "StringBuffer" );

toString( sb2 );

StringBuffer

(4)

sb3 := StringBuffer( "Another Buffer" );

sb3:=Object<<StringBuffer,139723741434016>>

(5)

toString( sb3 );

Another Buffer

(6)

sb4 := StringBuffer( sb3 );

sb4:=Object<<StringBuffer,139723741441632>>

(7)

toString( sb4 );

Another Buffer

(8)
• 

There are other special method names that can be defined. For a complete list of these methods, see the Overview of Objects in Maple page.

Operator Methods

• 

Objects in Maple can implement operator methods.  These methods will be invoked when objects are used with the corresponding operators in Maple. One can implement the = operator for StringBuffer as follows:

export `=`::static := proc( s1, s2, $ )
       if ( _npassed = 1 ) then
           return false;
       end;
       if ( not s1::{string,StringBuffer} or
               not s2::{string,StringBuffer} ) then
           return false;
       end;

       if ( s1::string ) then
           evalb(s1 = toString( s2 ));
       else
           if ( s2::string ) then
               evalb(toString( s1 ) = s2);
           elif ( s1 = s2 ) then
               true;
           else
               EqualEntries( s1:-buffer, s2:-buffer );
           end;
       end;
   end;

sb1 := StringBuffer( "Hello" );

sb1:=Object<<StringBuffer,139723741449280>>

(9)

sb2 := StringBuffer( "Hello" );

sb2:=Object<<StringBuffer,139723741453056>>

(10)

sb3 := StringBuffer( "Goodbye" );

sb3:=Object<<StringBuffer,139723741456736>>

(11)

evalb( sb1 = sb2 );

true

(12)

evalb( sb1 = sb3 );

false

(13)

evalb( sb1 = 1 );

false

(14)
• 

Note Checking for the 1 argument case handles the possibility that an object is compared to NULL.

evalb( sb1 = NULL );

false

(15)
• 

There are many operators that can be overloaded.  For a complete list, and more information about overloading operators, see the Objects Overloading Operators page.

Overriding builtin Routines

• 

Objects can override certain Maple routines of type builtin by defining a method with the same name.  For example, StringBuffer can implement a numelems member as follows.  

export numelems::static := proc( sb::StringBuffer, s::string, $ )
       :-numelems( sb:-buffer );
   end;

• 

When calling the top level numelems routine, we need to use the :- notation to differentiate from StringBuffer's numelems method.  Without this the StringBuffer numelems method would have an infinite recursion.

• 

With the numelems method defined, we can pass StringBuffer objects into numelems, just as we could other Maple structures.

numelems( [ 1, 2, 3 ] );

3

(16)

numelems( "Hello" );

5

(17)

numelems( sb );

11

(18)
• 

Not all builtin routines can be overridden.  For a complete list of routines that can be overridden and more discussion of overriding builtin routines, see Objects Overloading builtin Routines.

Examples

Here is the code from the sections above as a single declaration.

module StringBuffer()
   option object;

   local buffer := Array( 1..0, datatype=integer[1] );

   export ModuleCopy::static := proc( sb::StringBuffer, proto::StringBuffer,
           s::{string,StringBuffer,':-list'( ':-integer[1]' )}, $ )
       if ( _npassed = 3 ) then
           if ( s::':-string' ) then
               set( sb, s );
           elif ( s::':-list'( ':-integer[1]' ) ) then
               sb:-buffer := Array( s, datatype=integer[1] );
               NULL;
           else
               sb:-buffer := Array( s:-buffer );
               NULL;
           end;
       else
           sb:-buffer := Array( proto:-buffer );
           NULL;
       end;
   end;

   export ModuleApply::static := proc( )
       Object( StringBuffer, _passed );
   end;

   export numelems::static := proc( sb::StringBuffer, s::string, $ )
       :-numelems( sb:-buffer );
   end;

   export `=`::static := proc( s1, s2, $ )
       if ( _npassed = 1 ) then
           return false;
       end;
       if ( not s1::{string,StringBuffer} or
               not s2::{string,StringBuffer} ) then
           return false;
       end;

       if ( s1::string ) then
           evalb(s1 = toString( s2 ));
       else
           if ( s2::string ) then
               evalb(toString( s1 ) = s2);
           elif ( addressof(s1) = addressof(s2) ) then
               true;
           else
               EqualEntries( s1:-buffer, s2:-buffer );
           end;
       end;
   end;

   export set::static := proc( sb::StringBuffer, s::string, $ )
       sb:-buffer := Array( convert( s, ':-bytes' ), datatype=integer[1] );
       NULL;
   end;

   export toString::static := proc( sb::StringBuffer, $ )
       convert( convert(sb:-buffer,list), ':-bytes' );
   end;

   export append::static := proc( sb::StringBuffer, s::string, $ )
       local l, n;

       l := convert( s, ':-bytes' );

       n := :-numelems( sb:-buffer )+1;
       sb:-buffer( n..n+:-numelems(l)-1 ) := Array(l);
       NULL;
   end;
end;

See Also

module, ModuleApply, ModuleCopy, Object, object, object/builtin, object/create, object/operators, procedure


Download Help Document

Was this information helpful?



Please add your Comment (Optional)
E-mail Address (Optional)
What is ? This question helps us to combat spam