18. maj 2005 - 10:41Der er
12 kommentarer og 1 løsning
Eclipse / SUN compiler
Jeg er stødt på et (efter egen mening) lidt mærkeligt problem. For det første får jeg i nedenstående kode en warning fra Suns compiler, mens Eclipse giver mig en fejl. Det syntes jeg er lidt mystisk. For det andet, kan jeg slet ikke forstå, at jeg får hverken en warning eller en fejl :(
public class OBSClass <S extends OBSClass.SubjectImpl, O extends OBSClass.ObserverImpl>{ public abstract class ObserverImpl{ public void notify(S s){ s.getString(); } }
public abstract class SubjectImpl { protected HashSet<O> observers = new HashSet<O>();
public String getString(){ return "a string"; }
public void subscribe(O o){ observers.add(o); }
public void update(){ for(O o: observers){ o.notify(getThis()); } }
public abstract S getThis(); } }
Javas warning ser således ud: observerExample>javac -Xlint OBSClass.java OBSClass.java:24: warning: [unchecked] unchecked call to notify(S) as a member of the raw type observerExample.OBSClass.ObserverImpl o.notify(getThis());
Mens Eclipses fejl giver følgende: The method notify(OBSClass<S,O>.SubjectImpl) in the type OBSClass.ObserverImpl is not applicable for the arguments (S)
Sidste fejl siger mig, at den tror, at metoden notify tager et argument af typen SubjectImpl. Men hvorfor tror den det, når jeg explicit har sagt at det skal være typen S (som jo bare er en subtype af SubjectImpl).
Det skal måske lige siges, at den linie der producerer fejlen, er o.notify(getThis()); i metoden update() (så slipper i for at tælle ned til linie 24 ;)
Jeg har svært ved at se hvad man kan opnå ved det ene og ikke ved det andet (har dog heller ikke brugt generics ret meget) - dvs. jeg kan ikke rigtigt se din idé. Men hvis du vil benytte generics i metode kaldet så kan du vel prøve med:
public abstract <S extends OBSClass.SubjectImpl> S getThis();
Det jeg forsøger at gøre er, at lave et subject-observer pattern, som kan bruges med generics. Derved vil jeg opnå, at når man overrider en af metoderne, så skal man ikke caste til sit specielle subject eller observer, men kan bare bruge metoder derpå uden videre. Derved opnår man at man slipper for at caste, og så kan man undgå de der lækre runtime errors, som kan ske (hvis man er uopmærksom).
Problemet med at skrive public abstract SubjectImpl getThis(); er, at compileren ved type erasure fuldstændig vil slette typen S. Og så er man lige vidt i de "extendende" klasser.
Hmm... lad mig se om jeg har forstået det helt rigtigt... Hvis man vil benytte din observer pattern, så skal man som client nedarve fra bla. SubjectImpl og overskrive metoden public abstract SubjectImpl getThis() ?
Hvis dette er tilfældet, så har SUN med java 1.5 indført covariance (bruges f.eks. af generics) så du kan faktisk overskrive din metode således:
class TestSubjectImpl extends SubjectImpl{ @Override public TestSubjectImpl getThis() { return this; } }
Korrekt! Det kan man gøre. Men man kan også lade være. Og der er ingen måde at sikre at folk rent faktisk overskriver med det specifikke subject. Det ville der være hvis jeg skriver public abstract S getThis()...
Nej jeg kan ikke umiddelbart finde et link, men du kan jo evt. teste det selv ;0)
F.eks. kan du prøve at indsætte understående i eclipse og compile med 1.5 og med 1.4 så fremgår det klart at 1.4 ikke understøtter det men at det er lovligt i 1.5!
class TestSubjectImpl extends SubjectImpl{ @Override public TestSubjectImpl getThis() { return this; } }
Ok. Det jeg gjorde, var at forklare mig ud af den warning der fremkom. Det var ikke svært at overbevise om, at den ikke var fatal.
Desuden fandt jeg ud af, at i version 1.6 kommer der en funktion så man kan slå de enkelte warnings fra, hvis man forventer at de kommer men er ligeglad.
Tak for hjælpen, ellers. Hvis du vil dele pointene med mig, snoop_one, for dine forsøg så læg et svar.
Ok. Det tager jeg som et nej... jeg snupper dem selv...
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.