Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Expand
titleDel 1 - <tema> (xx%)Gender- og Person-klassene (30%)

Gender-klassen (vedlegg 1) representerer kjønnet til en person, i denne oppgaven begrenset til mann og kvinne. Klassen skal kodes slik at det ikke skal være mulig å ha andre Gender-objekter enn disse to kjønnene. En Gender-instans har et forklarende ord/navn knyttet til seg, som settes når instansen lages, og som ikke skal være direkte tilgjengelig fra andre klasser.

Oppgave a)

Hvilke modifikatorer bør stå foran deklarasjonen av label-feltet og konstruktøren? Begrunn svaret. 

Oppgave a)

 

Expand
titleLF

 

Oppgave b)

 

Expand
titleLF
 
Oppgave c)

 

Expand
titleLF

 

Oppgave d)

 

Expand
titleLF
 
Oppgave e)

Begge disse bør være markert som private, siden de ikke skal være tilgjengelig utenfor klassen. label bør også være final, siden den ikke skal kunne endres.

Oppgave b)

Hvordan er klassen kodet så det forklarende ordet/navnet vises ved utskrift, f.eks. med System.out.println(...)?

Expand
titleLF
Ved utskrift så brukes implisitt toString()-metoden, som er implementert og returnerer label.
Oppgave c)

Fullfør valueOf-metoden. 

Expand
titleLF
 
Oppgave f)

 

Expand
titleLF
 
Expand
titleDel 2 - <tema> (xx%)
Oppgave a)

 

Expand
titleLF

 

Oppgave b)

 

Expand
titleLF
 
Oppgave c)

 

Expand
titleLF
 
Oppgave d)

 

Expand
titleLF
 
Oppgave e)

 

Expand
titleLF
 
Oppgave f)

 

Expand
titleLF
 
Expand
titleDel 3 - <tema> (xx%)
Oppgave a)

 

Expand
titleLF

 

Oppgave b)

 

Expand
titleLF
 
Oppgave c)

 

Expand
titleLF
 
Oppgave d)

 

Expand
titleLF
 
Oppgave e)

 

Expand
titleLF
 
Oppgave f)

 

Expand
titleLF
 
Expand
titleDel 4 - <tema> (xx%)
Oppgave a)

 

Expand
titleLF

 

Oppgave b)

 

Expand
titleLF
 
Oppgave c)

 

Expand
titleLF
 
Oppgave d)

 

Expand
titleLF
 
Oppgave e)

 

Expand
titleLF
 
Oppgave f)

 

Expand
titleLF
 

Her er det viktig å returnere et eksisterende Gender-objekt, ved å sammenligne argumentet med label-verdien i de to konstantene MALE og FEMALE. En kan også bruke switch, som i Java 8 virker med String-objekter. valueOf ligner på Integer.valueOf og Double.valueOf og må være static, siden det er unaturlig og unødvendig å kalle den på en eksisterende instans.

Code Block
public static Gender valueOf(String label) {
   if (MALE.label.equals(label)) {
      return MALE;
   } else if (FEMALE.label.equals(label)) {
      return FEMALE;
   }
   return null;
}

Person-klassen (vedlegg 1) representerer en person, med et navn (String) og et kjønn (Gender). Navnet settes kun ved opprettelsen, mens kjønnet kan settes når som helst.

For å håndtere familieforhold så har et Person-objekt data om mor, far og barn. addChild-metoden brukes for å knytte et barn til en forelder, og det er ikke spesifisert andre metoder som endrer barn-forelder-koblingen. addChild både registrerer barnet og setter barnets kobling til mor eller far, avhengig av kjønnet til forelderen. Ta f.eks. kallet chris.addChild(pat), hvor pat blir registert som barnet til chris. Hvis chris er mann, så blir han registrert som pat sin far, mens hvis chris er kvinne, så blir hun registrert som pat sin mor.

Oppgave d)

Skriv felt, metoder og konstruktør for innkapsling av navn, kjønn, mor, og far. Bruk name, gender, mother og father som grunnlag for navngiving.

Expand
titleLF

Her er litt av poenget at en må ha en konstruktør som setter navnet og utelate set-metoder for name, mother og father.

Code Block
private final String name;
private Gender gender = null;
private Person father, mother;

public Person(String name) {
   this.name = name;
}


public String getName() {
   return name;
}

public Gender getGender() {
   return gender;
}

public void setGender(Gender gender) {
   this.gender = gender;
}

public Person getMother() {
   return mother;
}

public Person getFather() {
   return father;
}
Oppgave e)

Implementer getChildCount, hasChild og getChildren, med nødvendig(e) felt.

Expand
titleLF

Her må en ha riktig deklarasjon av feltet (helst Collection, sekundært List), og huske å initialisere feltet. getChildren må passe på å returnere en ny Collection, så annen kode ikke får tilgang til interne data. En må ta høyde for at gender kan være null. En kan gjerne bruke Stream-teknikken.

 

Code Block
private Collection<Person> children = new ArrayList<>();

public int getChildCount() {
   return children.size();
}

public boolean hasChild(Person child) {
   return children.contains(child);
}

// alternativ

public boolean hasChild(Person child) {
   return child.getFather() == this || child.getMother() == this;
}

public Collection<Person> getChildren(Gender gender) {
   Collection<Person> result = new ArrayList<>();
   for (Person child : children) {
      if (gender == null || child.getGender() == gender) {
         result.add(child);
      }
   }
   return result;
}
Oppgave f)

 

Expand
titleLF
 
Expand
titleDel 2 - <tema> (xx%)
Oppgave a)

 

Expand
titleLF

 

Oppgave b)

 

Expand
titleLF
 
Oppgave c)

 

Expand
titleLF
 
Oppgave d)

 

Expand
titleLF
 
Oppgave e)

 

Expand
titleLF
 
Oppgave f)

 

Expand
titleLF
 
Expand
titleDel 3 - <tema> (xx%)
Oppgave a)

 

Expand
titleLF

 

Oppgave b)

 

Expand
titleLF
 
Oppgave c)

 

Expand
titleLF
 
Oppgave d)

 

Expand
titleLF
 
Oppgave e)

 

Expand
titleLF
 
Oppgave f)

 

Expand
titleLF
 
Expand
titleDel 4 - <tema> (xx%)
Oppgave a)

 

Expand
titleLF

 

Oppgave b)

 

Expand
titleLF
 
Oppgave c)

 

Expand
titleLF
 
Oppgave d)

 

Expand
titleLF
 
Oppgave e)

 

Expand
titleLF
 
Oppgave f)

 

Expand
titleLF
 
Expand
titleAppendix 1
Code Block
/**
 * This class represents the gender of a Person.
 * It cannot be instantiated outside this class.
 * It provides all legal Gender values as static variables.
 */
public class Gender {

   ... String label;

   ... Gender(String label) {
      this.label = label;
   }

   @Override
   public String toString() {
      return label;
   }

   public static Gender
      MALE = new Gender("male"),
      FEMALE = new Gender("female");

   /**
    * Returns a pre-existing Gender instance for the provided label, or
    * null of there is no such instance.
    * @param label
    * @return a pre-existing Gender instance
    */
   ... Gender valueOf(String label) {
         ...
   }
}

public class Person implements Iterable<Person> {

   ... fields for name, gender, mother and father ...

   ... constructor ...

   ... methods for name, gender, mother and father ...
Expand
titleAppendix 1
Code Block
/**
 * This class represents the gender of a Person.
 * It cannot be instantiated outside this class.
 * It provides all legal Gender values as static variables.
 */
public class Gender {

   ... String label;

  field(s) for children ...

 Gender(String label) {
      this.label = label;/**
    * @return the number of children of this Person
   }

   @Override */
   public Stringint toStringgetChildCount() {
      return label;...
   }

   public/**
  static Gender
 * @param child
   MALE =* new Gender("male"),
      FEMALE = new Gender("female");

   /**
    * Returns a pre-existing Gender instance for the provided label, or
    * null of there is no such instance.
    * @param label@return if this Person has the provided Person as a child
    */
   public boolean hasChild(Person child) {
      ...
   }

   /**
    * Returns all children of this Person with the provided Gender.
    * @returnIf agender pre-existing Gender instance
    */is null, all children are returned.
   ... Gender* valueOf(String label) {
         ...Can be used to get all daughters or sons of a person.
   }
}

public class Person implements Iterable<Person> {
 * @param gender
   ... fields for name, gender, mother and father ...

   ... constructor */
   public Collection<Person> getChildren(Gender gender) {
      ...

   ... methods for name, gender, mother and father ...

   ... field(s) for children ...

   /**}

   /**
    * Adds the provided Person as a child of this Person.
    * Also @returnsets the number of children ofchild's father or mother to this Person,
    */
 depending  public int getChildCount() {
      ...
   }

   /**
    * @param childon this Person's gender.
    * To ensure consistency, if the provided Person already
    * has a parent of that gender,
    * @return if this Person has the provided Person as ait is removed as a child of that parent.
    * @param child
    */
   public booleanvoid hasChildaddChild(Person child) {
      ...
   }
}
   /**
    * Returns all children of this Person with the provided Gender.
public class PersonTest extends TestCase {

   public void testAddChild() {
    *  IfGender genderfemale is null= Gender.valueOf("female"), allmale children are returned.
= Gender.valueOf("male");
     * CanPerson bemother used= to get all daughters or sons of a person.
    * @param gender
    */
   public Collection<Person> getChildren(Gender gender) {
      ...
   }

   /**
    * Adds the provided Person as a child of this Person.
    * Also sets the child's father or mother to this Person,
    * depending on this Person's gender.
    * To ensure consistency, if the provided Person already
    * has a parent of that gender,
    * it is removed as a child of that parent.
    * @param child
    */
   public void addChild(Person child) {new Person("Chris"); mother.setGender(female);
      Person father1 = new Person("Pat");  father1.setGender(male);
      Person father2 = new Person("Alex"); father2.setGender(male);
      Person child = new Person("Jean");
      mother.addChild(child);
      assertEquals(1, mother.getChildCount());
      assertTrue(mother.hasChild(child));
      assertEquals(mother, child.getMother());
      mother.addChild(child);
      assertEquals(1, mother.getChildCount());

      father1.addChild(child);
      assertTrue(father1.hasChild(child));
      assertEquals(father1, child.getFather());

      father2.addChild(child);
      assertFalse(father1.hasChild(child));
      assertTrue(father2.hasChild(child));
      assertEquals(father2, child.getFather());

      father2.setGender(female);
      ...
   }
}

public class PersonTest extends TestCase {

   public void testAddChild() {
father2.addChild(child);
      // ???
      child.addChild(father2);
       Gender female = Gender.valueOf("female"), male = Gender.valueOf("male");// ???
   }
}

public class Family {
   /**
    * Adds a Person motheras =a new Person("Chris"); mother.setGender(female);
family member
    * @param person the Person father1 = new Person("Pat");  father1.setGender(male); to add
    */
   public void addMember(Person person) {
      ...
 Person father2 =}

 new Person("Alex"); father2.setGender(male); /**
    * Finds a Personmember childwith =the new Person("Jean");given name
    *  mother.addChild(child);@param name
    * @return the assertEquals(1, mother.getChildCount());
      assertTrue(mother.hasChild(child));
      assertEquals(mother, child.getMother());Person in this Family with the provided name
    */

   public Person  mother.addChild(child);findMember(String name) {
      assertEquals(1, mother.getChildCount());

...
   }

   father1.addChild(child);
      assertTrue(father1.hasChild(child));//

   /**
    * Writes assertEquals(father1, child.getFather());

      father2.addChild(child);the contents of this Family to the OutputStream,
      assertFalse(father1.hasChild(child));
      assertTrue(father2.hasChild(child));* so it can be reconstructed using load.
    *  assertEquals(father2, child.getFather());

@param out
      father2.setGender(female);
*/
   public void save(OutputStream out) father2.addChild(child);... {
      // ???...
   }

   child.addChild(father2);/**
    * Helper // ???
   }
}

public class Family {
   /**method that splits a line into a list of tokens,
    * Addseither awords Personor asquoted anames new(quotes familyare memberremoved).
    * @param line person- the Personstring to addtokenize
    */
   public... voidList<String> addMembertokenize(PersonString personline) {
      ... no need to implement this method ...
   }

   /**
    * FindsLoads acontents member withfrom the givenprovided name
InputStream into   * @param namethis Family.
    * @return@param the Person in this Family with the provided name
    */

   public Personvoid findMember(String name)load(InputStream in) ... {
      ...
   }
}

public interface Relation //
{
   /**
    * WritesReturns the contentsCollection of thisPersons Familyrelated to the provided OutputStream,Person
    * so it can be reconstructed using load.
    * @param out
    */
   public void save(OutputStream out) ... {according to this Relation.
    * E.g. if this Relation corresponds to the concept of niece,
    * it should return all Persons that are nieces of person.
    */
  ...
 Collection<Person> getRelativesOf(Person person);
}

   /**
    * Helper method that splits a line into a list of tokens,
    * either words or quoted names (quotes are removed).
    * @param line - the string to tokenize
    */
   ... List<String> tokenize(String line) {
      ... no need to implement this method ...
   }

   /**
    * Loads contents from the provided InputStream into this Family.
    * @param in
    */
   public void load(InputStream in) ... {
      ...
   }
}

public interface Relation {
   /*
    * Returns the Collection of Persons related to the provided Person
    * according to this Relation.
    * E.g. if this Relation corresponds to the concept of niece,
    * it should return all Persons that are nieces of person.
    */
   Collection<Person> getRelativesOf(Person person);
}

public class Relation2 implements Relation {

   public Relation2(Relation rel1, Relation rel2) {
      ...
   }

   @Override
   public Collection<Person> getRelativesOf(Person person) {
      ...
   }
}
public class Relation2 implements Relation {

   public Relation2(Relation rel1, Relation rel2) {
      ...
   }

   @Override
   public Collection<Person> getRelativesOf(Person person) {
      ...
   }
}
Expand
titleAppendix 2

The format is line-based, with three kinds of lines:

  1. A line with a gender label followed by a name (in quotes) indicates a new person with that gender and name.
  2. Otherwise the line is a sequence of names (in quotes) of persons, the first being the parent of the others (i.e. children).
  3. Empty, only whitespace or starting with #. Such lines are ignored when loading.

Lines of all types can be mixed, but there should be no forward references from lines of type 2 to lines of type 1. I.e. the names in lines of type 2 have previously occurred in lines of type 1. Below are two examples of the format.

Example 1:

Code Block
# all persons
# should result in a sequence of calls to Family's addMember method
male "Hallvard Trætteberg"
female "Marit Reitan"
male "Jens Reitan Trætteberg"
female "Anne Trætteberg Reitan"
# all mother/father-child relations
# should result in a sequence of calls to Person's addChild method
"Hallvard Trætteberg" "Jens Reitan Trætteberg" "Anne Trætteberg Reitan"
"Marit Reitan" "Jens Reitan Trætteberg" "Anne Trætteberg Reitan"

Example 2:

Code Block
male        "Hallvard Trætteberg"
male "Jens Reitan Trætteberg"
female "Anne Trætteberg Reitan"
"Hallvard Trætteberg" "Jens Reitan Trætteberg" "Anne Trætteberg Reitan"
female      "Marit Reitan"
"Marit Reitan" "Jens Reitan Trætteberg" "Anne Trætteberg Reitan"