/** New classes can be created by inheriting components from other classes,
    adding new components and overriding old ones.  The new class is called a
    subclass of the old one, which is called the superclass.  Inheritance is
    generally used when the subclasses may naturally be thought of as
    specializations of the superclass.

    Instances of the subclass are created by first creating an instance of the
    superclass, then allocating the instance variables of the subclass, then
    executing the subclasses constructor.  The superclass is instantiated by
    invoking one of its constructors in the subclass constructor, either
    explicitly (by calling super as the first statement) or implicitly (if no
    call to super appears).
*/

/* Movies, symphonies, operas are all special forms of attraction. */
class Attraction {

  /* Per-class default duration. */
  private static int defdur = 90;

  /* Per-instance actual duration. */
  private int duration = defdur;

  /* Methods to control access to instance variables. */

  public int duration () {
    return this.duration;
  }

  /* Constructor. */

  public Attraction (int d) {
    duration = d;
  }

}

/* A movie is a form of attraction. */
class Movie extends Attraction {

  /* Instance variables. */
  private int script, acting, directing;

  /* Constructor. */
  public Movie (int dur, int s, int a, int d) {
    super(dur);			// invoke the superclass constructor
    this.script = s; this.acting = a; this.directing = d;
  }
  
  /* Calculate the rating. */
  public int rating () {
    return (this.script + this.acting + this.directing);
  }

  /* Return a description of the attraction. */
  public String category () {
    return "Movie";
  }

}

/* A video is a form of movie. */
class Video extends Movie {

  /* Instance variables. */

  private String available;

  /* Constructor. */
  public Video (int dur, int s, int a, int d, String avail) {
    super(dur,s,a,d);			// invoke the superclass constructor
    this.available= avail;
  }
  

  /* Return a description of the attraction. */
  public String category () {
    return "Video";
  }

 /* Return availability of video. */
  public String thereis () {
    return "Yes";
  }

}

class Symphony extends Attraction {

  /* Rating parameters. */
  private int music, playing, conducting;

  /* Constructor. */
  public Symphony (int dur, int m, int p, int c) {
    super(dur);
    this.music = m; this.playing = p; this.conducting = c;
  }

  public int rating () {
    return music + playing + conducting;
  }

  public String category () {
    return "Symphony";
  }

}

/* An opera is a symphony (sort of) with acting and singing.  We override the
   rating method of the superclass to change its behavior for the subclass. */
class Opera extends Symphony {

  /* Rating parameters. */
  private int libretto, singing, acting;

  /* Constructor. */
  public Opera (int dur, int m, int p, int c, int l, int s, int a) {
    super (dur, m, p, c);	// invoke superclass constructor
    this.libretto = l; this.singing = s; this.acting = a;
  }

  /* Calculate rating as a function of the superclass's rating. */
  public int rating () {
    return (super.rating() + this.libretto + this.singing + this.acting);
  }

  public String category () {
    return "Opera";
  }

}

class InheritanceDemo {

  private static String report (String c, int r, int d) {
    return (c + " rating = " + r + ", duration = " + d);
  }
  
  private static String repp (String c, String av) {
    return (c + " available = " + av);
  }

  public static void main (String argv[]) {

    Symphony s = new Symphony(95, 8, 9, 8);
    Movie c = new Movie (90, 6, 7, 4);
    Opera o = new Opera (180, 8, 9, 8, 7, 8, 8);
    Video v = new Video (100, 5 , 5, 5, "Yes");
    System.out.println (report (s.category(), s.rating(), s.duration()));
    System.out.println (report (c.category(), c.rating(), c.duration()));
    System.out.println (report (v.category(), v.rating(), v.duration()));
    System.out.println (repp (v.category(), v.thereis()));

  }

}
