// CS100J Spring 2001
// Lecture 12, 3/1
// mechanics of objects

class Person {

    // instance variables
    // - called INSTANCE because not static
    // - they only exist when an object is created
    // - have unique values for each object
    // - shared by all other methods in the same object
    
    public String name;       // name of current Person
    public Person friend;     // friend of current Person is also a Person

    // constructor
    // - use constructors to set IVs usually, but can do even more!
    // - essentially a method, but a special kind
    // - automatically returns reference to object that is created

    public Person(String s) {
	name=s;
    } 
    
    // method for setting value of $friend$:
    public void set_friend(Person p) {
	friend = p;
    }

    // using $toString$ to print description of current object:
    public String toString() {
	return "Name of person: "+name+"; Name of friend: "+friend.name;
    }
}

public class lecture12 {
    public static void main(String[] args) {
	
	// create 4 new people:
	   Person a = new Person("Dave");
	   Person b = new Person("Jeff");
	   Person c = new Person("Nate");
	   Person d = new Person("Tony");

	// Dave's friend is Jeff
	// --------------------
	// bad style:
  	   a.friend = b;
	// better style:
	   a.set_friend(b);
	
	   // The difference becomes more apparent during discussion of
	   // information hiding and encapsulation -- you don't want to let
	   // someone else change a field directly, because someone else might
	   // be relying on the current value: using a method acts as a "guard"
	   // to prevent confusion.

        // Description of Dave:
	   System.out.println("Part 1:");
	   // toString automatically called when printing a reference
	   System.out.println(a.toString()); // redundant!
	   System.out.println(a);            // correct!

        // Creating objects as inputs and return values:
	   System.out.println("Part 2:");
	   b.set_friend(new Person("Alan"));
	   System.out.println(b);

	   // What I did was create a new Person object 
	   // As input to a method, the new object supplies an address
	   // You don't actually get or need a reference variable
	   // In this case, the dummy argument of set_friend $p$ acts as 
	   // the reference variable.
	   // More important: remember that a new object did get created!

        // Aliases
        // if you assign a reference to an object to another reference
        // an object gets obliterated...which one?

	   c = d; 
 
	   // + $c$ gets the address of $d$
	   // + so, the object that $c$ referred to is gone
	   // + $c$ now refers to the same object that $d$ does
	   // + changes to $c$ and $d$ affect eachother because they mean the
	   //   the same object

	   System.out.println("Part 3:");
	   c.set_friend(b);
           System.out.println(a);
           System.out.println(b);
	   System.out.println(c);
           System.out.println(d);
    }
    
}

/* output:
Part 1:
Name of person: Dave; Name of friend: Jeff
Name of person: Dave; Name of friend: Jeff
Part 2:
Name of person: Jeff; Name of friend: Alan
Part 3:
Name of person: Dave; Name of friend: Jeff
Name of person: Jeff; Name of friend: Alan
Name of person: Tony; Name of friend: Jeff
Name of person: Tony; Name of friend: Jeff
*/