| 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
end
Here 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
Car.m, its instances may be created by calling its constructor and
setting the properties.
>>mycar=new Car();
>>mycar.setMake("toyota")
>>mycar.setModel("camry")
>>mycar.setYear(2010);
>>"My car is a ",mycar
My 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:
var attributename.
[...]=obj.methodname(...), where obj
is an instance of the class obtained by an expression of the form
obj=new ClassName(...) with appropriate inputs. 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)
>>a
Millenimum 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)
>>a
x:
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 |
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.
>>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 ]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
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 ]