abstract class PersonList { //To calculate the number of descendents in this PersonList abstract int numDescendents(); } class EmptyPL extends PersonList { // new EmptyPL().numDescendents() == 0 //To calculate the number of descendents in this EmptyPL int numDescendents() { // ... return 0; } } class LargerPL extends PersonList { Person first; PersonList rest; LargerPL( Person first, PersonList rest ) { this.first = first; this.rest = rest; } //new LargerPL( new Someone( "Bob", new EmptyPL()), new EmptyPL()).numDescendents() == 1 //new LargerPL( new Someone( "Bob", new LargerPL( new Someone("Kate", new EmptyPL()), new EmptyPL()) ), // new LargerPL( new Someone( "Fred", new EmptyPL()), new EmptyPL())).numDescendents() == 3 //To calculate the number of descendents in the LargerPL int numDescendents() { // ... this.first.PersonMethod() ... this.rest.PersonListMethod() ... return 1 + this.first.numDescendents() + this.rest.numDescendents(); } } class JP { // new JP().iNowPronounce( new Someone("Jack",new EmptyPL()), new Someone("Jill",new EMptyPL()) ) -> // Jack.spouse == Jill; Jill.spouse == Jack //To join p1 and p2 in marriage void iNowProunounce( Person p1, Person p2 ) { // .. p1 .. p2 p1.marryMe(p2); p2.marryMe(p1); } } abstract class Person { // To marry this person to another abstract void marryMe( Person to ); // To add a kid of this Person abstract void addKid( String name ); // To calculate the number of descendents of this Person abstract int numDescendents(); } class Noone extends Person { // To marry this noone to another Person void marryMe( Person to ) { } // To add a kid of this Noone void addKid( String name ) { } // new Noone().numDescendents() == 0 //To calculate the number of descendents of this Noone int numDescendents() { return 0; } } class Someone extends Person { String name; Person spouse; PersonList kids; Someone ( String name, PersonList kids ) { this.name = name; this.spouse = new Noone(); this.kids = kids; } //Someone Tom = new Someone("Tom", new EmptyPL()); //Someone mary = new Someone( "Mary", new EmptyPL() ); // Tom.marryMe( mary ); // new Someone("Tom", new EmptyPL()).marryMe( // new Someone("Mary", new EmptyPL()) ) // Someone( "Tom", Noone() ,EmptyPL()) --> Someone( "Tom", Someone("Mary", Noone(), EmptyPL()) EmptyPL()) // Tom.spouse -> Noone() ==> Tom.spouse == mary //To marry this Someone to another Person void marryMe( Person to ) { // ... this.name ... this.spouse.PersonMethod() ... this.kids.PersonListMethod() ... to this.spouse = to; } // Tom.addKid( "Jo" ) -> void // Someone( "Tom", mary, EmptyPL() ) -> Someone( "Tom", mary, LargerPL( Someone("Jo", EMptyPL() ) // Tom.kids -> EmptyPL ==> Tom.kids -> LargerPL( Someone("Jo"..), EmptyPL) //To add a kid of this Someone void addKid( String name ) { // ... this.name ... this.spouse.PersonMethod() ... this.kids.PersonListMethod() ... name ... this.kids = new LargerPL( new Someone ( name, new EmptyPL() ), this.kids ); } // Tom.numDescendents() == 1 //new Someone("Bob", new LargerPL( new Someone("Fred", new EmptyPL()), // new LargerPL( new Someone("Sally", new LargerPL( new Someone("Dan",new EmptyPL()), new EmptyPL())), // new EmptyPL()))).numDescendents() == 3 // To calculate the number of descendents in this Someone int numDescendents() { // ... this.name ... this.spouse.PersonMethod() ... this.kids.PersonListMethod() ... return this.kids.numDescendents(); } }