Lösungsvorschläge zum Übungsblatt 11: Fortgeschrittene Aspekte

Transcription

Lösungsvorschläge zum Übungsblatt 11: Fortgeschrittene Aspekte
Prof. Dr. A. Poetzsch-Heffter
Dipl.-Inform. N. Rauch
Technische Universität Kaiserslautern
Fachbereich Informatik
AG Softwaretechnik
Lösungsvorschläge zum Übungsblatt 11: Fortgeschrittene Aspekte
objektorientierter Programmierung (SS 2007)
Aufgabe 1 Generics und Comparable
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
abstract class TischA implements Comparable<TischA> {
private int numCorners;
private int numLegs;
private int tableSize;
public TischA( int numCorners, int numLegs, int tableSize ){
this.numCorners = numCorners;
this.numLegs = numLegs;
this.tableSize = tableSize;
}
public int compareTo(TischA that) {
return this.tableSize < that.tableSize ? -1 :
this.tableSize == that.tableSize ? 0 : 1;
}
}
class RunderTischA extends TischA {
public RunderTischA( int numLegs, int tableSize ){
super( 0, numLegs, tableSize );
}
}
class EckigerTischA extends TischA {
public EckigerTischA( int numCorners, int numLegs, int tableSize ){
super(numCorners, numLegs, tableSize );
}
}
class TestA {
public static void main( String[] s ){
RunderTischA rt1 = new RunderTischA( 4, 100 );
RunderTischA rt2 = new RunderTischA( 1, 120 );
EckigerTischA et1 = new EckigerTischA( 3, 3, 70 );
EckigerTischA et2 = new EckigerTischA( 4, 1, 110 );
List<EckigerTischA> eckig = Arrays.asList(et1, et2);
assert Collections.max(eckig) == et2;
List<RunderTischA> rund = Arrays.asList(rt1, rt2);
assert Collections.max(rund) == rt2;
List<TischA> gemischt = Arrays.asList(et1, rt2);
assert Collections.max(gemischt) == rt2;
System.out.println("Alles ok.");
}
}
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
abstract class TischB {
private int numCorners;
private int numLegs;
private int tableSize;
public int getCorners(){
return numCorners;
}
public int getLegs(){
return numLegs;
}
public TischB( int numCorners, int numLegs, int tableSize ){
this.numCorners = numCorners;
this.numLegs = numLegs;
this.tableSize = tableSize;
}
}
class RunderTischB extends TischB implements Comparable<RunderTischB> {
public RunderTischB( int numLegs, int tableSize ){
super( 0, numLegs, tableSize );
}
public int compareTo(RunderTischB that) {
return this.getLegs() < that.getLegs() ? -1 :
this.getLegs() == that.getLegs() ? 0 : 1;
}
}
class EckigerTischB extends TischB implements Comparable<EckigerTischB> {
public EckigerTischB( int numCorners, int numLegs, int tableSize ){
super(numCorners, numLegs, tableSize );
}
public int compareTo(EckigerTischB that) {
return this.getCorners() < that.getCorners() ? -1 :
this.getCorners() == that.getCorners() ? 0 : 1;
}
}
class TestB {
public static void main( String[] s ){
RunderTischB rt1 = new RunderTischB( 4, 100 );
RunderTischB rt2 = new RunderTischB( 1, 120 );
EckigerTischB et1 = new EckigerTischB( 3, 3, 70 );
EckigerTischB et2 = new EckigerTischB( 4, 1, 110 );
List<EckigerTischB> eckig = Arrays.asList(et1, et2);
assert Collections.max(eckig) == et2;
2
List<RunderTischB> rund = Arrays.asList(rt1, rt2);
assert Collections.max(rund) == rt2;
List<TischB> gemischt = Arrays.<TischB>asList(et1, rt2);
// assert Collections.max(gemischt) == rt2; // compile-time error
System.out.println("Alles ok.");
}
}
Aufgabe 2
Wildcards
This is a long, complex generic method signature. Let’s walk through it:
The method has a type variable T with complicated bounds that we’ll return to later.
The method returns a value of type T.
The name of the method is max( ).
The method’s argument is a Collection. The element type of the collection is specified with a bounded wildcard. We
don’t know the exact type of the collection’s elements, but we know that they have an upper bound of T. That is, we
know that the elements of the collection are type T or a subclass of T. Any element of the collection could therefore
be used as the return value of the method.
That much is relatively straightforward. We’ve seen upper-bounded wildcards elsewhere in this section. Now let’s look
again at the type variable declaration used by the max( ) method:
<T extends Comparable<? super T> > This says first that the type T must implement Comparable. (Generics syntax
uses the keyword extends for all type variable bounds, whether classes or interfaces.) This is expected since the purpose
of the method is to find the “maximum” object in a collection. But look at the parameterization of the Comparable
interface. This is a wildcard, but it is bounded with the keyword super instead of the keyword extends. This is a lowerbounded wildcard. ? extends T is the familiar upper bound: it means T or a subclass. ? super T is less commonly used:
it means T or a superclass.
To summarize, then, the type variable declaration states “T is a type that is comparable to itself or to some superclass
of itself.”
Aufgabe 3
Wildcards
package blatt11.lsg;
import java.util.List;
public class Aufgabe3<T> {
private T value;
public List<? super T> addValue(List<? super T> l) {
l.add(value);
return l;
}
public List<? extends T> extractValue(List<? extends T> l) {
value = l.remove(0);
return l;
}
public List<T> replaceValue(List<T> l) {
l.add(value);
value = l.remove(0);
return l;
}
3
}
Aufgabe 4
Generics und Typauslöschung
a) Eine nicht-generische Variante der Klasse StringList könnte so aussehen:
package blatt11.lsg;
import java.util.ArrayList;
public class StringList extends ArrayList {
private static final long serialVersionUID = 1L;
@Override
public boolean add(Object s){
return add((String)s);
}
public boolean add(String s){
return super.add("String # " + (size()+1) + ": " + s );
}
@Override
public String get(int index) {
return "At pos " + index + ": " + super.get(index);
}
}
b) Methoden der generischen Klasse StringList:
public
public
public
public
java.lang.String blatt11.StringList.get(int)
volatile java.lang.Object blatt11.StringList.get(int)
boolean blatt11.StringList.add(java.lang.String)
volatile boolean blatt11.StringList.add(java.lang.Object)
(Es sollte eigentlich bridge heißen statt volatile, dies ist ein Fehler in Java 5.)
c) In diesem Fall werden keine Methoden in die Klasse StringListLeer hineingeneriert. Die generierten Methoden
decken ja den Fall ab, dass ein Typparameter in einer Methodensignatur durch einen konkreten Typ ungleich
Object ersetzt wurde und bei der Typauslöschung damit keine Überschreibungsbeziehung mehr vorhanden ist,
da die Methodensignatur den Typparameter durch Object ersetzt. Da in StringListLeer jedoch keine Methode
überschrieben wurde, tritt der Fall gar nicht auf.
4