/** A person has a first and last name. */
public class Person {
  private String firstName;
  private String lastName;
  
  /** create a person with the given first and last names.
    * precondition: neither first nor last contain the ' ' character.
    */
  public Person(String firstName, String lastName) {
    assert !firstName.contains(" ");
    assert !lastName.contains(" ");
    
    this.firstName= firstName;
    this.lastName= lastName;
  }
  
  public String getName() {
    return firstName + ' ' + lastName;
  }
}

/** A PhD is a person with a graduation year. */
class PhD extends Person {
  private int graduationYear; // not in the future
  
  /** create a PhD with given first and last names and graduation year 
    * pre: names are not null and don't contain ' ',
    * gradYear is not in the future. */
  public PhD(String firstName, String lastName, int gradYear) {
    // to call a superclass's constructor, use the *super* keyword:
    super(firstName, lastName); // sets first and last name fields
    graduationYear = gradYear; // then we can set PhD-specific fields
    /*
     * notes about calling superclass constructors:
     * --if you explicitly call a superclass constructor, it must be on the
     *   FIRST line of the constructor
     * --you MUST call some superclass constructor. if you don't explicitly
     *   call one, java will implicitly call super() as the first line.
     * --if your superclass has no zero-parameter constructor (true in this
     *   example), the implicit super() will give an error because it doesn't
     *   exist!
     */
  }
 
  public String getName() {
    // to call a method from my superclass, use super like this:
    return super.getName() + ", PhD (" + graduationYear + ")";
    
    // without super, getName() would make a recursive call to this method! 
  }
  
  public String getHumbleName() {
    // again we need super:
    return super.getName();
    
    // but if this class doesn't override a method, the bottom-up
    // rule will automatically find the most-specific implementation
    // of the method and call it. for example, a call to
    //   toString()
    // in PhD will call Object's toString after failing to find a toString
    // defined in PhD and Person (in that order).
  }
}
