You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 2 Next »

 I denne oppgaven skal dere skrive kode for 3 klasser relatert til desimaltall med benevning:

  • Unit, som er en klasse for enhet/benevning,

Strukturen av kode og metoder det skal jobbes med på denne eksamen, er samlet i vedlegget. Oppførselen er spesifisert i strukturerte kommentarer over klasser og metoder. Det blir henvist til vedlegget i hele oppgavesettet.

 Oppgave a)
Unit-klassen er utformet slik at instanser ikke skal kunne endres etter at de er opprettet. Hva er generelle fordeler og ulemper med klasser som gir ikke-modifiserbare (immutable) instanser?

Klassen blir enklere, og minsker bl.a. behovet for validering. Instanser kan brukes av flere deler av et program, uten risiko for at en del endrer på dem og ødelegger for en annen del. Ulempen er at en må lage nye instanser hvis de må rettes på, istedenfor å endre dem direkte.

Oppgave b)
Skriv ferdig de tre konstruktørene og definer nødvendige felt. Hva er hensikten med bruken av throws-nøkkelordet, slik det er brukt her? Er det strengt tatt nødvendig og evt. hvorfor/hvorfor ikke?
private final String symbol;
public Unit(String symbol) throws IllegalArgumentException {
	this(symbol, null, 1.0, 0.0);
}
private final Unit base;
private final double factor, offset;
public Unit(String symbol, Unit base, double factor, double offset) throws IllegalArgumentException {
	for (int i = 0; i < symbol.length(); i++) {
		char c = symbol.charAt(i);
		if (! Character.isAlphabetic(c)) {
			throw new IllegalArgumentException(c + " is an illegal symbol character");
		}
	}
	this.symbol = symbol;
	this.base = base;
	this.factor = factor;
	this.offset = offset;
}
public Unit(String symbol, Unit base, double factor) throws IllegalArgumentException {
	this(symbol, base, factor, 0.0);
}

throws-deklarasjonen forteller leseren av koden at konstruktørene kan utløse unntak. Siden unntakene er en subklasse av RuntimeException og dermed ikke checked, så er det ikke nødvendige.

Oppgave c)
Hva er hensikten med å definere en toString()-metode?

toString()-metoden brukes implisitt når Java lager String-objekter av instanser ifm. bruk av + og IO og sikrer at tilstanden til instanser blir presentert på en nyttig måte.

Oppgave d)

Nederst i klassen defineres en del meter-relaterte Unit-instanser (m, km og dm og cm). Tegn objektdiagram som illustrerer objektstrukturen som disse instansene utgjør.

Her er verdiene til feltene og kjeden av base-linker vesentlig.

Oppgave e)
Metoden findCommonBaseUnit er sentral i konvertering av verdier mellom ulike enheter. Den skal virke slik at dm.findCommonBaseUnit(km) returnerer m-instansen. Skriv ferdig metoden.
public Unit findCommonBaseUnit(Unit other) {
	Unit unit1 = this;
	while (unit1 != null) {
		Unit unit2 = other;
		while (unit2 != null) {
			if (unit2 == unit1) {
				return unit1;
			}
			unit2 = unit2.base;
		}
		unit1 = unit1.base;
	}
	return null;
}
Oppgave f)
convert-metoden er ferdigskrevet og bruker de to hjelpemetodene convertToBase og convertFromBase. De to hjelpemetodene kaller også seg selv. Forklar hvilke kall som gjøres til disse (inkludert de til seg selv) og hvilke argumenter de får og verdier de returnerer, i løpet av utførelsen av dm.convert(2.0, km).
...
Oppgave g)
valueOf-metoden ”oversetter” fra et enhetssymbol til en Unit-instans, litt på samme måten som Double.valueOf lager en Double-verdi fra en String. Men merk at Unit.valueOf ikke skal lage nye instanser, men returnere en av de predefinerte! Skriv ferdig valueOf-metoden.
public static Unit valueOf(String symbol) {
	for (Unit unit : ALL_UNITS) {
		if (symbol.equals(unit.symbol)) {
			return unit;
		}
	}
	return null;
}
 Oppgave a)

 Hva er hensikten med get-metoder? Fullfør konstruktøren, get-metodene og deklarer nødvendige felt.

 get-metoder gir tilgang til tilstanden uten å ”avsløre” hvilke felt som brukes for å representere tilstanden.

private final Unit unit;
private final double value;
public Value(Unit unit, double value) {
	this.unit = unit;
	this.value = value;
}
public Unit getUnit() {
	return unit;
}
public double getValue() {
	return value;
}


Oppgave b)
valueOf-metoden ”oversetter” fra en String til en Value-instans, litt på samme måten som Double.valueOf lager en Double-verdi fra en String. Skriv ferdig valueOf-metoden.
public static Value valueOf(String s) {
	int pos = s.length();
	while (Character.isAlphabetic(s.charAt(pos - 1))) {
		pos--;
	}
	return new Value(Unit.valueOf(s.substring(pos)), Double.valueOf(s.substring(0, pos)));
}
Oppgave c)
Skriv ferdig add, compute og mult-metodene.
public Value add(Value other) {
	Unit base = this.unit.findCommonBaseUnit(other.unit);
	double sum = this.unit.convert(value, base) + other.unit.convert(other.value, base);
	return new Value(base, sum);
}
public Value compute(BinaryOperator<Double> op, double other) {
	double result = op.apply(this.value, other);
	return new Value(this.unit, result);
}	
public Value mult(double other) {
	return compute((v1,  v2) -> v1 * v2, other);
}
Oppgave d)
Value-klassen implementerer Comparable<Value>. Hvorfor er det nyttig? Skriv ferdig compare-metodene.

Ved å implementere Comparable-grensesnittet så kan Value-objekter sorteres vha. Java sine innebygde sort-metoder.

public int compareTo(Value other) {
	Unit base = this.unit.findCommonBaseUnit(other.unit);
	if (base == null) {
		throw new IllegalArgumentException("Cannot compare " + this + " with " + other);
	}
	double d1 = this.unit.convert(value, base), d2 = other.unit.convert(other.value, base);
	if (d1 < d2) {
		return -1;
	} else if (d1 > d2) {
		return 1;
	} else {
		return 0;
	}
}
Oppgave a)

Values-grensesnittet utvider Iterable<Double>. Hvorfor er det nyttig/praktisk?

 
Oppgave b)

Values-grensesnittet er ment å støtte observerbarhet og observert-observatør-teknikken, men deklarasjonen av metodene for lytterhåndtering er erstattet av ”…”. Skriv de to deklarasjonene.

public void addValuesListener(ValuesListener listener);
public void removeValuesListener(ValuesListener listener); 
Oppgave c)

Skriv ferdig konstruktøren og de to appendValue-metodene i ValueSeries-klassen. Definer nødvendige felt.

private final Unit unit;
private Collection<Double> values  = new ArrayList<Double>();
public ValueSeries(Unit unit) {
	this.unit = unit;
}
public void appendValue(double value) {
	values.add(value);
	fireValuesChanged();
}
public void appendValue(Value value) {
	appendValue(value.getUnit().convert(value.getValue(), getUnit()));
}
Oppgave d)
Implementer metodene i ValueSeries-klassen, som er nødvendige for å gjøre klassen komplett.
@Override
public int size() {
	return values.size();
}
@Override
public double average() {
	double sum = 0.0;
	for (double value : values) {
		sum += value;
	}
	return sum / values.size();
}
@Override
public Unit getUnit() {
	return unit;
}
@Override
public Iterator<Double> iterator() {
	return values.iterator();
}
//
@Override
public Values add(Values other) {
	Unit base = this.unit.findCommonBaseUnit(other.getUnit());
	ValueSeries result = new ValueSeries(base);
	Iterator<Double> otherDoubles = other.iterator();
	for (double value : values) {
		double otherDouble = otherDoubles.next();
		double sum = this.unit.convert(value, base) + other.getUnit().convert(otherDouble, base);
		result.appendValue(sum);
	}
	return result;
}
// ValuesListener support
private Collection<ValuesListener> listeners = new ArrayList<ValuesListener>();
@Override
public void addValuesListener(ValuesListener listener) {
	listeners.add(listener);
}
@Override
public void removeValuesListener(ValuesListener listener) {
	listeners.remove(listener);
}
protected void fireValuesChanged() {
	for (ValuesListener listener : listeners) {
		listener.valuesChanged(this);
	}
}

I denne delen skal du skrive testkode for Value- og ValueSeries-klassene. Hensikten er å vise at du behersker testmetodikken, og du kan, men trenger ikke bruke JUnit-rammeverket.  

Oppgave a)

Skriv testkode for Value sin valueOf-metode.

public void testValueOf() {
	Value value = Value.valueOf("2.0m");
	assertEquals(Unit.valueOf("m"), value.getUnit());
	assertEquals(2.0, value.getValue());
}


Oppgave b)

 

 

 

  • No labels