Avatar billede martinhrj Nybegynder
18. maj 2005 - 10:41 Der 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 :(

Koden ser således ud:

package observerExample;
import java.util.HashSet;

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).

Håber der er en der har svar på mine spørgsmål.

På forhånd tak!
Avatar billede martinhrj Nybegynder
18. maj 2005 - 11:00 #1
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 ;)
Avatar billede snoop_one Nybegynder
18. maj 2005 - 23:37 #2
Prøv at ændre linien:
  public abstract S getThis();
til:
  public abstract SubjectImpl getThis();
Avatar billede martinhrj Nybegynder
19. maj 2005 - 10:24 #3
Ja, det er klart. Så bliver problemet løst. Men så forsvinder hele idéen med hvorfor jeg gør som jeg gør, også :(

Men som jeg også skriver... så er parametertypen i notify jo S. Så hvorfor kan getThis() ikke returnere S, og så virker det?
Avatar billede snoop_one Nybegynder
19. maj 2005 - 10:35 #4
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();
Avatar billede martinhrj Nybegynder
19. maj 2005 - 10:43 #5
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.
Avatar billede snoop_one Nybegynder
20. maj 2005 - 10:58 #6
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;
  }
}
Avatar billede martinhrj Nybegynder
21. maj 2005 - 09:10 #7
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()...
Avatar billede martinhrj Nybegynder
21. maj 2005 - 09:11 #8
Har du forøvrigt et link der bekræfter at der er indført covariance? Det har jeg ikke set nogen steder...
Avatar billede snoop_one Nybegynder
21. maj 2005 - 10:28 #9
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;
  }
}
Avatar billede snoop_one Nybegynder
23. maj 2005 - 20:50 #10
Er problemet løst?
Avatar billede martinhrj Nybegynder
23. maj 2005 - 21:16 #11
Nej, ikke endnu. Der kom lige et andet projekt i vejen. Men jeg er snarest igang med det igen, og har ikke helt glemt tråden her endnu.

Jeg skal nok se, om jeg ikke kan huske at skrive, når jeg finder ud af noget ;)
Avatar billede martinhrj Nybegynder
01. juni 2005 - 08:32 #12
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.
Avatar billede martinhrj Nybegynder
06. juni 2005 - 15:52 #13
Ok. Det tager jeg som et nej... jeg snupper dem selv...
Avatar billede Ny bruger Nybegynder

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.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester