|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
toStringmethod to the class which is called by the interpreter to construct a string representation of instances of the class for display. Once the class
Carhas 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
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:
objis an instance of the class obtained by an expression of the form
obj=new ClassName(...)with appropriate inputs.
staticto 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.
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)(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
and the trigonometric functions
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
objis 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 ]