Avatar billede soreno Praktikant
08. februar 2006 - 09:33 Der er 11 kommentarer og
3 løsninger

Problemer med abstract class

Jeg sidder og eksperimentere med template method pattern og er stødt på et problem jeg ikke kan finde en fornuftig løsningen på.

Følgende kode:
abstract class Foo {
  protected Foo() {
    System.out.println(getText());
  }
  protected abstract String getText();
}

class Bar extends Foo {
  protected Bar() {
    super();
  }

  protected String getText() {
    return "Bar";
  }
}

class Baz extends Foo {
  protected String str = "Baz";
  protected Baz() {
    super();
  }

  protected String getText() {
    return str;
  }
}

Giver ved denne kode:
    Foo f;
    f = new Bar();
    f = new Baz();

Følgende output:
Bar
null

Problemet er at getText returnere en variabel som tilsyneladende ikke er initialiseret (fordi super kaldes som det første i klassens constructor).

Det må da kunne løses (uden at skulle teste for null i getText) ?

Nogle forslag ?
Avatar billede _carsten Nybegynder
08. februar 2006 - 12:31 #1
Tvivler på der skulle være en løsning på det, egentlig er det vel fornuftigt nok det der sker, superklassens konstruktør kaldes først, implicit eller explicit og sørger for at superklassen er fuldt initieret inden subklasse inititeres, i superklassen's konstruktør kalder du getText() som returnerer værdien af variablen "str", den er nødt til at være null da subklassen ikke er initieret.

Men du kan jo checke for null i Foo og så den vel klaret
Avatar billede soreno Praktikant
08. februar 2006 - 16:04 #2
Men lige præcis i forbindelse med template method pattern synes jeg det er lidt uhensigtsmæssig.
Avatar billede arne_v Ekspert
08. februar 2006 - 17:11 #3
Jeg tror ikke at Java er eneste sprog som vil have problemer med den konstruktion.

Det virker fint med alt andet en constructor.

Min erfaring er at man tit er bedst stillet med kun simple initailiseringer
i constructor.
Avatar billede _carsten Nybegynder
08. februar 2006 - 17:17 #4
Man vil vel heller ikke kalde en abstract metode fra konstruktør når man på forhånd ved der ikke kommer noget fornuftigt ud af det, da subklasse på det tidspunkt ikke kan være initieret.
Avatar billede simonvalter Praktikant
08. februar 2006 - 18:06 #5
brug evt en
protected abstract void initialize();
i superklassen der kaldes før du laver noget på metoderne
og initaliser alle ikke statiske variabler i den.
Avatar billede soreno Praktikant
15. februar 2006 - 08:42 #6
simonvalter:

Hvordan skulle det kunne løse problemet med at kalde en subklasses metode i konstruktøren på superklassen ?
Jeg kan jo ikke kalde initialize i konstruktøren.
Avatar billede simonvalter Praktikant
15. februar 2006 - 08:53 #7
Jeg forstår sikkert ikke hvad du mener.. men hvorfor kan du ikke kalde initalize i konstruktøren?

Her er hvad jeg mente..

abstract class Foo {
    protected Foo() {
        initialize();
        System.out.println(getText());
    }

    protected abstract String getText();
    protected abstract void initialize();
}

class Bar extends Foo {
    protected Bar() {
        super();
    }

    protected String getText() {
        return "Bar";
    }

    protected void initialize() {}
}

class Baz extends Foo {

    protected String str = /* drop at initalisere her */ "Baz";

    protected Baz() {
        super();
    }

    protected String getText() {
        return str;
    }

    // Gør det her istedet
    protected void initialize() {
        str = "Baz";
    }

    public static void main(String[] args) {
        Foo foo = new Bar();
        foo = new Baz();
    }
}
Avatar billede soreno Praktikant
15. februar 2006 - 08:58 #8
Men, problemet er jo at jeg ikke kan kalde en subklasses metode før subklassen er konstrueret. Og jeg formoder at en klasse først er konstrueret efter at konstruktøren returnerer. Dermed kan jeg ikke fra superklassen kalde en metode i subklassen (fordi subklassen kalder superklassens konstruktør).
Avatar billede simonvalter Praktikant
15. februar 2006 - 09:48 #9
I forhold til dit eksempel så virker det jo at gøre sådan.
Jeg er for træt til at grave i jls nu men som jeg husker det så er objektet rigtig nok først konstruret _færdigt_ når constructor afslutter men det betyder ikke du ikke kan kalde en metode. Du kan få problemer som du jo også gør her... og at stole på at folk initaliserer i en bestemt metode er måske heller ikke den bedste ide? men det virker.
Avatar billede soreno Praktikant
15. februar 2006 - 09:52 #10
Ah ja, du har ret.
I mit eksempel havde jeg glem at kalde init() i konstruktøren. Så er det jo klart det ikke virker :-)

Kan i ikke alle smide et svar.
Avatar billede simonvalter Praktikant
15. februar 2006 - 10:00 #11
ok
Avatar billede soreno Praktikant
21. februar 2006 - 10:58 #12
Det står tilsyneladende lidt sløjt til med at smide de svar..
:-)

Næste gang jeg kommer i tanke om at jeg har dette åbne spørgsmål vil jeg fordele point blandt dem som har smidt et svar.
Avatar billede arne_v Ekspert
21. februar 2006 - 18:25 #13
jeg synes ikke at jeg har bidraget med meget, men her er et alligevel
Avatar billede _carsten Nybegynder
22. februar 2006 - 17:36 #14
Så pyt da.
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