Nice

Contributed by Isaac Gouy

Shape class (shape.nice)

/*
The Java implementation style could be used with Nice.
Instead, let's imagine we've already written Shape, Rectangle
and Circle - as they are given below.

In a separate file we'll extend and use these classes.
*/


abstract class Shape {                 // class definition
   int x;
   int y;

   void moveTo(int x, int y);          // method declaration
   void moveBy(int dx, int dy);
}

moveTo(this@Shape, newx, newy){  // method implementation
   x = newx;
   y = newy;
}

moveBy(this@Shape, dx, dy){
   x += dx;
   y += dy;
}



class Rectangle extends Shape {        // Nice will create a default constructor
   private int width;
   private int height;

   void setHeight(int height);
   void setWidth(int width);
}


setHeight(this@Rectangle, height){
   this.height = height;
}

setWidth(this@Rectangle, width){
   this.width = width;
}



class Circle extends Shape {           // Nice will create a default constructor
   private int radius;

   void setRadius(int radius);
}

setRadius(this@Circle, radius){
   this.radius = radius;
}

Try shapes function (tryshape.nice)

/*
The Java implementation style could be used with Nice.
Instead, let's assume we want to extend and re-use the classes defined
in shape.nice. Let's also assume we want to define an interface so doSomething
isn't restricted to Shape subclasses.
*/

<IShape S> void doSomething( S shape ){
   shape.draw;
   shape.moveByI(100, 100);
   shape.draw;
}



// so our abstract interface should include moveBy and draw
// currently we have to use a different name than moveBy
// (in future we'll be able to qualify moveBy with a package name)

abstract interface IShape {
   void moveByI(int dx, int dy);
   void draw();
}



// the Shape class is already written - we need it to implement IShape

class shapes.Shape implements IShape;



// the nice compiler will detect that the Shape classes don't
// implement draw methods - so let's implement them

draw(this@Rectangle){
   println("Drawing a Rectangle at (" + x + ", " + y +
         "), width " + width + ", height " + height);
}

draw(this@Circle){
   println ("Drawing a Circle at (" + x + "," + y + "), radius " + radius);
}



// the Shape classes have a moveBy method
// they need a moveByI method for the IShape interface

moveByI(this@Shape, dx, dy){
   this.moveBy(dx, dy);
}



// we've extended the Shape classes Rectangle and Circle for the IShape interface
// let's use them

void main(String[] args){
   Shape[] scribble = [
      new Rectangle(x: 10, y: 20, width: 5, height: 6),
      new Circle(x: 15, y: 25, radius: 8)
      ];

   for (int i=0; i<scribble.length; ++i)
      doSomething( scribble[i] );

   Rectangle rect = new Rectangle(x: 0, y: 0, width: 15, height: 15);
   rect.setWidth(30);
   rect.draw;
}