/** Classes can have instances, called objects, with per-instance fields and
    methods.  The non-static components of the class are per-instance; the
    static components are per-class and shared among all instances.

    An instances is created by calling a constructor.  Constructors are
    functions with the same name as the class.  There may be many
    constructors, distinguished by the number and types of their arguments.

    An instance is created by allocating a fresh copy of the dynamic fields, 
    called the instance variables, and binding them to the non-static methods
    of the class.  The instance itself is bound to the pseudo-variable "this"
    for use within the methods of the class so that the methods can access the
    fields and call the other methods of the instance.

    The public components of an object are accessed using "dot notation".  The
    private components are only accessible within the methods of the class.
    Static methods may not access dynamic fields or methods; they are
    essentially functions internal to the class that do not have access to
    the internals of any instance.  Dynamic methods may, of course, access
    static components.

    (Credit: movie examples derived from Winston and Narasimhan "On To Java".)  */

/* A class of movies.  Each movie has a title and rating parameters, with
   a method to calculate its overall rating and a public, non-assignable title
   field.
*/

class Movie {

  /* Per-class weights for rating parameters. */
  private static final int sweight = 6, aweight = 13, dweight = 11;

  /* Per-instance title field, initialized by the constructors. */
  public final String title ;

  /* Per-instance rating parameters. */
  private int script, acting, directing;

  /* Calculate the (weighted) rating. */
  public int rating () {
    return sweight*this.script + aweight*this.acting + dweight*this.directing;
  }

  /* Construct an instance with the specified parameters. */
  public Movie (String t, int s, int a, int d) {
    this.title = t; this.script = s; this.acting = a; this.directing = d;
  }
  
  /* By default, construct a mediocre movie. */
  public Movie () {
    this.title = "Untitled"; this.script = 5; this.acting = 5; this.directing = 5;
  }

}

/* Create two movies, one with specified rating parameters.  Then print their
   composite ratings. */
class DynamicDemo {

  private static void report (Movie m) {
    System.out.println ("Rating of " + m.title + " is " + m.rating());
  }

  public static void main (String argv[]) {
    Movie titanic = new Movie ("Titanic", 8, 9, 6);
    Movie anon = new Movie ();
    report (titanic);
    report (anon);
  }

}
