// discussed
//   - extends
//   - bottom-up rule and overriding methods
//   - protected fields
//   - super(), super.method(), this()
//   - Object, toString, equals


// useful Object methods:
//
// toString(): return a human-readable String representing the Object
// equals(Object o2): indicates whether this is "equal to" o2.


/** A person has a first and last name. */
// extends Object is automatic if no other superclass declared.
// everything extends Object, either directly or indirectly
public class Person /* extends Object */ {
	
	// protected: visible to this class and any subclasses
	protected String firstName;
	protected 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;
	}

	/** create a person named "John Doe". */
	public Person() {
		// Note: in a real application I would not include this (John Doe is so arbitrary!).
		// I included it here so I'd have a default constructor below.
		
		// calls the Person(String, String) constructor.
		// must be first line!
		this("john", "doe");

		// these are done by the other constructor:
		// this.firstName = "john";
		// this.lastName  = "doe";
		
	}

	/** = the first and last name of this person. */
	public String getName() {
		return this.firstName + "  " + this.lastName;
	}

	// @Override tells compiler that you intend to override.  Catches typos and informs reader!
	@Override
	public String toString() {
		return getName();
	}
	
	/** two Persons are equal if they have the same first name */
	@Override
	public boolean equals(Object other) {
		// return this.firstName.equals(other.firstName); fails because Object has no firstName field. 
		//
		// we'll implement properly next time; for now, just use Object.equals
		return super.equals(other);
	}
	
	public static void main(String[] args) {
		// every Doctor is a Person!
		Person p1 = new Doctor("john", "doe", 3);
		
		// System.out.println(p1.toString()); same as
		System.out.println("" + p1);
		// concatenation automatically calls toString()
		
		Person p2 = new Person();
		System.out.println(p2.toString());
	}
	
}

/** A Doctor IS a person with a graduation year. */
// can't be public in file with a different name, sorry!
// In a real application, I would put Doctor in Doctor.java (not to be confused with DrJava!)
// and make it public
//
// with no class modifier, Doctor is "package protected"; more on this later.
class Doctor extends Person {
	
	private int graduationYear; // in 0..2016

	public Doctor(String first, String last, int gradYear) {
		// explicitly calls superclass constructor Person(String,String)
		super(first,last);
		// superclass constructor does these:
		// this.firstName = first;
		// this.lastName  = last;
		
		// if you leave super call out: Java automatically calls super()
		// impossible to create a Person without calling some Person constructor!
		// (which is good: otherwise you might violate a private Person invariant)

		this.graduationYear = gradYear;
	}
	
	public Doctor() {
		super();
		this.graduationYear = 2016;
	}
	
	@Override
	public String getName() {
		// super.getName calls getName() in superclass.
		// follows bottom-up rule, but starts at superclass.
		return super.getName() + ", PhD, (grad " + graduationYear + ")";
	}
}
