[Java] Objecten vervangen

Pagina: 1
Acties:

  • Funcracker
  • Registratie: Juni 2001
  • Laatst online: 28-04 18:17

Funcracker

The LedZ Collective

Topicstarter
Na zoeken op Google en alhier ben ik er nog immer niet uit. Is het in Java mogelijk om een object te vervangen door een object van hetzelfde type (class) of lager (subclass)?

Ik heb een object "Vrucht" en een object "Aardbei" dat Vrucht extends.

Nu wil heb ik verschillende objecten die allemaal references hebben naar een enkel object van type Vrucht. Eén van die objecten echter gaat ervoor zorgen dat dit object evolueert naar een Aardbei.

Als ik zijn reference vervang door een reference naar een nieuwe object Aardbei dan ben ik voor dat ene object klaar. Maar de rest verwijst nog immer naar de Vrucht. Ik moet dus het geheugen waarin de Vrucht nu is opgeslagen daadwerkelijk aanpassen zodat er een Aardbei in komt te zitten.

Is zoiets mogelijk of kan ik op een andere wijze alle references eenvoudig (of minder eenvoudig) naar een ander stuk geheugen (lees: object) laten verwijzen?

I am one hell of a guy, I can do anything I want, only I just don't have the faintest idea what.
Zaphod Beeblebrox, in The Hitch Hiker's Guide To The Galaxy


  • Michali
  • Registratie: Juli 2002
  • Laatst online: 22-03 18:12
Je zou dan direct het geheugen moeten bewerken dermate van pointers (zoals in c++), maar dat is echter niet mogelijk in Java (als ik me niet vergis). Is het niet mogelijk om gewoon op de plaatsten waar je een aarbei nodig hebt hem even te upcasten? Anders zou ik het ook niet weten.

Noushka's Magnificent Dream | Unity


  • Funcracker
  • Registratie: Juni 2001
  • Laatst online: 28-04 18:17

Funcracker

The LedZ Collective

Topicstarter
Michali schreef op dinsdag 29 maart 2005 @ 13:42:
Je zou dan direct het geheugen moeten bewerken dermate van pointers (zoals in c++), maar dat is echter niet mogelijk in Java (als ik me niet vergis). Is het niet mogelijk om gewoon op de plaatsten waar je een aarbei nodig hebt hem even te upcasten? Anders zou ik het ook niet weten.
Nope, want ik heb echt die ene specifieke instantie van de Aardbei nodig. Het gaat dus echt om de referentie.

I am one hell of a guy, I can do anything I want, only I just don't have the faintest idea what.
Zaphod Beeblebrox, in The Hitch Hiker's Guide To The Galaxy


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

[antwoord op je vraag]
Gewoon ff een wrapper erom heen plaatsen. Iedereen wijst naar die wrapper.. en als je dan de interne verwijzing in die wrapper naar het echte object vervangt, heeft iedereen een nieuwe vrucht.
Het state-designpattern zou eventueel ook een oplossing kunnen zijn. het borduurd verder op de wrapper, maar van buitenaf is het voor iedereen een vrucht ipv een dom wrapper object.

[opmerkingen]
Ik weet niet waar jij dit voor nodig bent dus ik kan ook niet oordelen of dit een goeie oplossing is. Maar mijn vermoeden is dat je door ander oo ontwerp tot een betere oplossing kan komen. Instanties van objecten verwisselen alleen omdat je een ander type hebt gekregen kan duiden op een fout ontwerp.

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 22-03 18:12
Dan is de oplossing om een strategy/state pattern te gebruiken. Je gooit dan de functionaliteit van de functies in andere classes en behoudt deze als instance in een member veld.
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class StandaardVrucht
{
  public void doeIets()
  {
    // doe iets
  }
}

class Aarbei extends StandaardVrucht
{
  public void doeIets()
  {
    // doe iets anders
  }
}

class Vrucht
{
  private StandaardVrucht vrucht;

  public Vrucht()
  {
    vrucht = new Aarbei();
  }

  public void setVrucht(StandaardVrucht vrucht)
  {
    this.vrucht = vrucht;
  }

  public void doeIets()
  {
    vrucht->doeIets();
  }
}

Je zit dan alleen wel met losse methods die niets uitvoeren als de vrucht in een bepaalde staat is.

Noushka's Magnificent Dream | Unity


  • Funcracker
  • Registratie: Juni 2001
  • Laatst online: 28-04 18:17

Funcracker

The LedZ Collective

Topicstarter
Alarmnummer schreef op dinsdag 29 maart 2005 @ 13:46:
[antwoord op je vraag]
Gewoon ff een wrapper erom heen plaatsen. Iedereen wijst naar die wrapper.. en als je dan de interne verwijzing in die wrapper naar het echte object vervangt, heeft iedereen een nieuwe vrucht.
Het state-designpattern zou eventueel ook een oplossing kunnen zijn. het borduurd verder op de wrapper, maar van buitenaf is het voor iedereen een vrucht ipv een dom wrapper object.

[opmerkingen]
Ik weet niet waar jij dit voor nodig bent dus ik kan ook niet oordelen of dit een goeie oplossing is. Maar mijn vermoeden is dat je door ander oo ontwerp tot een betere oplossing kan komen. Instanties van objecten verwisselen alleen omdat je een ander type hebt gekregen kan duiden op een fout ontwerp.
Thnx voor het wrapper idee, dat is zeker mogelijk, doch vind ik persoonlijk een wat omslachtige manier. Aan de andere kant is het wel een nette Java manier waarschijnlijk :P Netter dan wat ik hier wil. Als ik dit zou willen doen dan zou ik van mijn Vrucht een soort halve wrapper maken die dan dus een pointer bezit naar een subclass van zichzelf. Als die niet null is, gebruikt hij dat object in zijn methodes in plaats van zichzelf. Hoe netjes zou dat zijn?

Over je tweede punt: Ik heb het voor het gemak over vruchten en aardbeien, maar in werkelijkheid gaat het hier niet over :) Toch is de analogie prima en is het zo dat een hele hoop objecten verwijzigingen hebben naar tig verschillende vruchten. Zodra één van die objecten besluit de Vrucht te laten evolueren naar een Aardbei dienen alle andere objecten, die refereces hadden naar de deze vrucht, hier rekening mee te houden. Ze moeten hun Vrucht object voortaan behandelen als een Aardbei en er niet zelf laten een Banaan van proberen te maken omdat ze nog niet doorhebben dat het reeds een Aardbei was.

Ik weet uit mijn hoofd niet of daar een mooi OO-model voor bestaat helaas.

I am one hell of a guy, I can do anything I want, only I just don't have the faintest idea what.
Zaphod Beeblebrox, in The Hitch Hiker's Guide To The Galaxy


  • Michali
  • Registratie: Juli 2002
  • Laatst online: 22-03 18:12
Een wrapper gaat toch goed? Je kan eventueel een class maken met 2 functies en 1 veld: getObject() setObject en object. Zoals alarmnummer al zei kun je zo het object zetten en overal weer ophalen. Je kunt dan in een class het object ophalen en geupcast weer terug stoppen.

Edit: je zult dan echter wel moeten bijhouden wat voor object je nu opgeslagen hebt. Hiervoor mischien een aparte set functies toevoegen? Anders is een state/strategy oplossing toch het beste.

[ Voor 27% gewijzigd door Michali op 29-03-2005 14:03 ]

Noushka's Magnificent Dream | Unity


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Funcracker schreef op dinsdag 29 maart 2005 @ 13:57:
[...]
Ik weet uit mijn hoofd niet of daar een mooi OO-model voor bestaat helaas.
State design pattern :)

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
interface Vrucht{
    void knijpErin();
    void gooiErmee();
}

class VruchtWrapper implements Vrucht{
    
    void setVrucht(Vrucht vrucht){
        _vrucht = vrucht;
    }
    
    void knijpErin(){
        _vrucht.knijpErin();
    }
    
    void gooiErmee(){
        _vrucht.gooiErmee();
    }
}


Een vruchtwrapper kun je nu zien als een volwaardige vrucht:

Vrucht v = new VruchtWrapper(aardbei)//constructor moetje nog ff aanmaken
v.knijpErin();

Maar nogmaals.. deze oplossing is niet gratis. Je krijgt bv identiteits problematiek (equals/hashproblematiek in collections).. heeft bepaalde consequenties voor concurrency control.

[ Voor 67% gewijzigd door Alarmnummer op 29-03-2005 14:23 ]


  • Funcracker
  • Registratie: Juni 2001
  • Laatst online: 28-04 18:17

Funcracker

The LedZ Collective

Topicstarter
Michali schreef op dinsdag 29 maart 2005 @ 14:02:
Een wrapper gaat toch goed? Je kan eventueel een class maken met 2 functies en 1 veld: getObject() setObject en object. Zoals alarmnummer al zei kun je zo het object zetten en overal weer ophalen. Je kunt dan in een class het object ophalen en geupcast weer terug stoppen.

Edit: je zult dan echter wel moeten bijhouden wat voor object je nu opgeslagen hebt. Hiervoor mischien een aparte set functies toevoegen? Anders is een state/strategy oplossing toch het beste.
Yupz, een wrapper zou ook zeker kunnen. Jouw voorstel ziet er ook goed uit.

Maar om even terug te komen op mijn originele vraag: Het is dus niet mogelijk om het object daadwerkelijk in het geheugen te vervangen door een subclass? Of om alle referenties naar het object te laten verwijzen naar het nieuwe object?

Met wrappers ga ik er wel uitkomen, maar ik gebruik ze liever niet. Wil het graag simpel houden :P

I am one hell of a guy, I can do anything I want, only I just don't have the faintest idea what.
Zaphod Beeblebrox, in The Hitch Hiker's Guide To The Galaxy


  • Michali
  • Registratie: Juli 2002
  • Laatst online: 22-03 18:12
Funcracker schreef op dinsdag 29 maart 2005 @ 14:16:
Maar om even terug te komen op mijn originele vraag: Het is dus niet mogelijk om het object daadwerkelijk in het geheugen te vervangen door een subclass? Of om alle referenties naar het object te laten verwijzen naar het nieuwe object?
Naar mijn weten niet.

Noushka's Magnificent Dream | Unity


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Kan een vrucht ook andere attributen krijgen als het in een ander type veranderd? Kan een object ook andere methode implementaties krijgen als het in een ander type verandert? Zo nee dan zou ik gewoon een VruchtType aanmaken en geen Vrucht subclasses. Iedere vrucht is van een bepaald vrucht type (je geeft iedere vrucht dus een attribuut vruchttype). Dit is een eenvoudige maar binnen de door mij genoemde voorwaarden tevens de beste oplossing.

[edit]
Als je trouwens wel andere methode implementaties nodig bent zou je deze ook in VruchtType kunnen definieeren en de vrucht als invoer meegeven aan die methodes.

[ Voor 28% gewijzigd door Alarmnummer op 29-03-2005 14:35 ]


  • Funcracker
  • Registratie: Juni 2001
  • Laatst online: 28-04 18:17

Funcracker

The LedZ Collective

Topicstarter
Alarmnummer schreef op dinsdag 29 maart 2005 @ 14:25:
Kan een vrucht ook andere attributen krijgen als het in een ander type veranderd? Kan een object ook andere methode implementaties krijgen als het in een ander type verandert? Zo nee dan zou ik gewoon een VruchtType aanmaken en geen Vrucht subclasses. Iedere vrucht is van een bepaald vrucht type (je geeft iedere vrucht dus een attribuut vruchttype). Dit is een eenvoudige maar binnen de door mij genoemde voorwaarden tevens de beste oplossing.

[edit]
Als je trouwens wel andere methode implementaties nodig bent zou je deze ook in VruchtType kunnen definieeren en de vrucht als invoer meegeven aan die methodes.
Yupz, dat is zeker een mooie (imho ;)) oplossing. Echter hebben ze wel degelijke verschillende attributen en methode implementaties.

I am one hell of a guy, I can do anything I want, only I just don't have the faintest idea what.
Zaphod Beeblebrox, in The Hitch Hiker's Guide To The Galaxy


  • The-MeLLeR
  • Registratie: Juni 2004
  • Laatst online: 27-02 11:20

The-MeLLeR

3l33t

Je moet gebruik maken van een "Interface".
Dit houd in dat je een klasse maakt met alleen maar lege methodes.

Zoiets als dit:
Java:
1
2
3
public interface Vrucht{
 public void blaat(){}
}

Dan kan je je aardbei deze late implementeren:
Java:
1
2
3
4
5
public class Aardbei{
public void blaat(){
//doe iets
}
}

Hierdoor kan je alle vruchten typecasten naar de Vrucht interface:
Java:
1
2
Aardbei aardbei = new Aardbei;
Vrucht vrucht = (Vrucht)aardbei;

[ Voor 8% gewijzigd door The-MeLLeR op 29-03-2005 15:02 ]


  • Daos
  • Registratie: Oktober 2004
  • Niet online
Dat laatste kan wel, maar of het mooi wordt is iets anders.

Het kan op twee manieren:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import java.util.*;

public class Vrucht {
  private static int id = 0;
  private String naam = this.getClass().getName() + id++;
  public String toString() {
    return naam;
  }

  // voor maakVanVruchtEenAardbei2
  private Vector eigenaars = new Vector();

  // voor 2
  public void voegEigenaarToe(Eigenaar e) {
    eigenaars.add(e);
  }

  // 2
  public void veranderInDezeAardbei(Aardbei a) {
    for (int i = 0; i < eigenaars.size(); i++) {
      ((Eigenaar)eigenaars.get(i)).vervangVruchtDoorDezeAardbei(a);
    }
  }
}


public class Aardbei extends Vrucht{
}


import java.util.*;

public class Eigenaar {
  private static int id = 0;
  private String naam = this.getClass().getName() + id++;
  public String toString() {
    return naam + " bezit " + v;
  }

  // 1
  private static Vector eigenaars = new Vector();

  private Vrucht v;

  public Eigenaar(Vrucht v) {
    this.v = v;
    // 2
    v.voegEigenaarToe(this);
    // 1
    eigenaars.add(this);
  }

  // 1
  public void maakVanVruchtEenAardbei1() {
    Aardbei a = new Aardbei();
    Vrucht v = this.v;
    for (int i = 0; i < eigenaars.size(); i++) {
      ((Eigenaar)eigenaars.get(i)).vervangDezeVruchtDoorDezeAardbei(v, a);
    }
  }

  // 2
  public void maakVanVruchtEenAardbei2() {
    v.veranderInDezeAardbei(new Aardbei());
  }

  // 2
  public void vervangVruchtDoorDezeAardbei(Aardbei a) {
    v = a;
  }

  // 1
  public void vervangDezeVruchtDoorDezeAardbei(Vrucht v, Aardbei a) {
    if (this.v == v)
      this.v = a;
  }
}


public class Start {
  public static void main(String[] args) {
    Vrucht v0 = new Vrucht();
    Vrucht v1 = new Vrucht();

    Eigenaar e0 = new Eigenaar(v0);
    Eigenaar e1 = new Eigenaar(v0);
    Eigenaar e2 = new Eigenaar(v1);
    Eigenaar e3 = new Eigenaar(v1);


    System.out.println(e0);
    System.out.println(e1);
    System.out.println(e2);
    System.out.println(e3);

    e0.maakVanVruchtEenAardbei1();
    e2.maakVanVruchtEenAardbei2();

    System.out.println(e0);
    System.out.println(e1);
    System.out.println(e2);
    System.out.println(e3);
  }
}

[ Voor 32% gewijzigd door Daos op 29-03-2005 16:46 ]


  • Funcracker
  • Registratie: Juni 2001
  • Laatst online: 28-04 18:17

Funcracker

The LedZ Collective

Topicstarter
@Daos: Hehe, leuk idee. Mijn probleem is echter dat ik geen Vector heb met alle objecten die, die ene vrucht bevatten. Ik kan dus niet via mijn Vrucht bij die objecten komen. Alleen andersom is dat mogelijk.

I am one hell of a guy, I can do anything I want, only I just don't have the faintest idea what.
Zaphod Beeblebrox, in The Hitch Hiker's Guide To The Galaxy


  • Hielko
  • Registratie: Januari 2000
  • Nu online
Volgens mij de suggestie van The-MeLLeR de suggestie die je zoekt.

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 22-03 18:12
Hielko schreef op dinsdag 29 maart 2005 @ 16:32:
Volgens mij de suggestie van The-MeLLeR de suggestie die je zoekt.
Volgens mij niet. De andere referenties refereren nog steeds naar een aardbei volgens mij.

Noushka's Magnificent Dream | Unity


  • Funcracker
  • Registratie: Juni 2001
  • Laatst online: 28-04 18:17

Funcracker

The LedZ Collective

Topicstarter
Michali schreef op dinsdag 29 maart 2005 @ 16:34:
[...]


Volgens mij niet. De andere referenties refereren nog steeds naar een aardbei volgens mij.
Yup. Dat is niet de juiste oplossing. Ik kan niet al die references casten (helaas).

I am one hell of a guy, I can do anything I want, only I just don't have the faintest idea what.
Zaphod Beeblebrox, in The Hitch Hiker's Guide To The Galaxy

Pagina: 1