Reflection.

Extending a Java class.

Implementing Java interfaces.

Overloading operators and functions.

Definition of a class |

A class may be defined in Mathnium to encapsulate a set of data objects and functions in objects which are instances of the class.

The simplest example of a class is a *bean* which is a collection of
properties ( which are attributes/fields of the instances of the class).

class Car var make; var model; var year; function Car() // Constructor end function toString() return sprintf("%s %s made in %d\n",make,model,year) end endHere we have added a

`toString`

method to the class which
is called by the interpreter to construct a string representation of instances
of the class for display.
Once the class `Car`

has been defined, preferably in a file
>>mycar=new Car();>>mycar.setMake("toyota")>>mycar.setModel("camry")>>mycar.setYear(2010);>>"My car is a ",mycarMy car is a toyota camry made in 2010.>>mycar.getYear()2010

Here the getter and setter methods `setMake`

, `setModel`

,
`getModel`

etc.,
even though not explicity implemented in the class definition, have been
added to the class by the interpreter for each of the attributes of the class.

In summary, a class definition may include the following:

- A set of zero or more attributes, declared by using statments of the form
`var`

.*attributename* - A
*constructor*, which is defined just as any Mathnium function, except that a constructor may not have any outputs, and its name is the name of the class. - A set of zero or more
*methods*, which are just functions within the enclosing class defintion. These methods are not visible outside the class definition, and may be called by expressions of the form

, where*[...]=obj.methodname(...)*`obj`

is an instance of the class obtained by an expression of the form

with appropriate inputs.*obj*=new*ClassName(...)* - The method and attribute definition may be preceded by the keyword
`static`

to define static mthods or fields. Such methods and fields are shared by all instances of the class. The static fields may be initialized in a static method`initClass`

, which, if defined, is called once for each class before the first instance of the class is constructed.

A class can be *extended* as follows:

class FancyCar extends Car var maximumSpeed function FancyCar() end function toString() return super.toString()+" can go up to "+maximumSpeed+ " mph." end end

As in Java, a class may not extend more than a single class.

The new class inherits the properties and methods of its parent.>>a=new FancyCar()>>a.setModel("Super Racer")>>a.setMake("Millenium")>>a.setYear(2015)>>a.setMaximumSpeed(350)>>aMillenimum Super Racer made in 2015 can go up to 350 mph.

## Reflection |

The following functions may be used to elicit information about classes that are defined

`fieldnames(MyClass.class)`

returns the names of the fields in the declared class.`setfield(obj, fieldname, value)`

sets the value of the given field for an instance of a class.`getfield(obj, fieldname)`

returns the value of the given field for an instance of a class.`constructors(MyClass.class)`

returns the constructor of the class as an array of one element.`methods(MyClass.class)`

returns the methods of the class as an array.`method(MyClass.class, methodname)`

returns the method of the class with the given name.

The outputs of the last three functions may be used to invoke the methods/constructor of a class by specifying appropriate inputs.

>>class A>var x>function A(x);this.x=x;end>function add(y);return new A(x+y);end>static function addab(a,b);return new A(a.x+b.x);end>end>> // invoke the constructor>> // Equivalent to a=new A(2)>>a=constructors(A.class)[1](2)>>ax: 2>>method(A.class,"add")Method ($returnValue) =A.add(y)>>// Equivalent to a.add(10)>>method(A.class,"add")(a,10)x: 12>>// Equivalent to A.addab(new A(10),new A(12))>>method(A.class,"addab")(new A(10),new A(12))x: 22

## Extending a Java class |

Mathnium classes that extend Java classes may also be defined. The following class extends the Java Swing frame.

class MyFrame extends JFrame import javax.swing.*; var name var address var ok var cancel var nameLabel var addressLabel function MyFrame() super() createComponents() add(createLayoutPanel()) end function createComponents() // define buttons ok=new JButton("OK"); cancel=new JButton("Cancel"); ok.addActionListener(@this.okClicked); cancel.addActionListener(@this.cancelClicked); // define textfields name=new JTextField(20) address=new JTextField(20) // define Labels nameLabel=new JLabel("Name") addressLabel=new JLabel("Address") end function createLayoutPanel() // Layout is a class that has static cover methods // for the methods of pagelayout.EasyCell // see http://pagelayout.sourceforge.net/docs/ // We import the various methods of the class by using the // importStatic call. importStatic(Layout.class); // Row of buttons bottomrow=row("right","center",ok,cancel); bottomrow.linkWidth(cancel,1,ok) // The content panel return pagepanel( grid("right","center", nameLabel,name,eol(), addressLabel, address,eol(), bottomrow, hspan())); end function okClicked(e) "You entered name as\n" " "+name.getText()+NL+"and address as\n" " "+address.getText()+NL end function cancelClicked(e) "You canceled the entries\n" end end

The following usage of the class leads to the GUI shown below.

>>a=new MyFrame()>>a.pack()>>a.show()

## Implementing Java interfaces |

In the previous example, the event listeners are assigned to the buttons by using the Mathnium mechanism for the implicit creation of interface proxies if the argument to a Java method that requires an interface with a single method is a Mathnium function. Alternatively, and more transparently, an existing Java interface can be implemented explicitly in a Mathnium class.

class ButtonFrame implements ActionListener import javax.swing.*; import java.awt.event.*; function ButtonFrame() frame=new JFrame(); button=new JButton("Click me"); frame.add(pagepanel(Layout.row(button))); button.addActionListener(this); frame.pack(); frame.show(); end function actionPerformed(e) "You clicked me\n" end end

Clearly, in this case, the class definition must include methods whose names (and the size of the argument list) are identical to the methods specified by the interface to be implemented.

## Overloading functions and operators |

Operators and functions may be overloaded
for the objects defined by a Mathnium class. The following class
is defined to implement the automatic differentiation algorithm for
addition, multiplication,
and the trigonometric functions `sin`

, and `cos`

.

class MyDeriv var f var fx function MyDeriv(f,fx) this.f=f; this.fx=fx; end // Overload addition: d(p+q)/dx=dp/dx+dq/dx function +(other) return new MyDeriv(f+other.f,fx+other.fx); end // Overload multiplication: d(p*q)/dx=q*dp/dx+p*dq/dx function *(other) return new MyDeriv(f*other.f,fx*other.f+f*other.fx); end // Overload sin: d(sin(p))/dx=cos(p)*dp/dx function sin() return new MyDeriv(Main.sin(f),Main.cos(f)*fx) end // Overload cos: d(cos(p))/dx=-sin(p)*dp/dx function cos() return new MyDeriv(Main.cos(f),-Main.sin(f)*fx) end // This method, if defined, is called by the interpreter // if one of the operands is not an instance of this class. static function convert(x) REAL x # Make sure it's real SCALAR x # Make sure it's a scalar return new MyDeriv(x,0); end function toString() return "["+f+","+fx+"]"; end end

Note that a *static* method has been defined here. Any static
method can be defined in a class as in Java (as also static attributes/fields).
Also note that it is a good practice to use the prefix *Main.* for
calling the usual Mathnium function from within a class that overloads
functions.

Although the syntax as exemplified above for evaluating the expressions involving objects with overloaded operators and functions is quite adequate, Mathnium has a mechanism that makes the usage much more convenient: a call of the form>>xv=new MyDeriv(pi/3,1) // x and derivative of x at x=pi/3>>xv.sin() // sin(x) and derivative of sin(x) at x=pi/3[0.866 ,0.5 ]>>(2*xv).sin() // sin(2*x) and derivative of sin(2*x) at x=pi/3[0.866 ,-1 ]>>(xv*xv).cos() // cos(x*x) and derivative of cos(x*x) at x=pi/3[0.4566 ,-1.8633 ]>>(xv*xv*xv).cos() // cos(x*x*x) and derivative of cos(x*x*x) at x=pi/3[0.41 ,-3.0007 ]>>(xv*xv) // x*x and derivative of x*x at x=pi/3[1.0966 ,2.0944 ]

`func(obj,...)`

is interpreted as
`obj.func(...)`

if `obj`

is an instance of
a Mathnium class that has a method `func`

. Thus the following
expressions have the same values as the corresponding expressions above.
>>xv=new MyDeriv(pi/3,1) // x and derivative of x at x=pi/3>>sin(xv) // sin(x) and derivative of sin(x) at x=pi/3[0.866 ,0.5 ]>>sin(2*xv) // sin(2*x) and derivative of sin(2*x) at x=pi/3[0.866 ,-1 ]>>cos(xv*xv) // cos(x*x) and derivative of cos(x*x) at x=pi/3[0.4566 ,-1.8633 ]>>cos(xv*xv*xv) // cos(x*x*x) and derivative of cos(x*x*x) at x=pi/3[0.41 ,-3.0007 ]>>(xv*xv) // x*x and derivative of x*x at x=pi/3[1.0966 ,2.0944 ]