[Java] Typeconversie van objecten

Pagina: 1
Acties:

  • coenbijlsma
  • Registratie: Augustus 2004
  • Niet online
Geachte medetweakers,

volgende week heb ik een tentamen van een inleiding in Java programmeren, waarbij we het oa ook geleerd hebben wat typeconversie inhoudt. Daarvan kan je kort het volgende zeggen:
  1. Je kunt niet zijdelings in de hiërarchie verplaatsen,
  2. Je kunt zonder problemen omhoog verplaatsen,
  3. Je kunt niet omlaag in de hiërarchie verplaatsen zonder dat je expliciet cast.
Om dit een beetje te illustreren het volgende voorbeeld:

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
class Animal {
   private int weight = 0;

   public void setWeight(int initWeight) {
      weight = initWeight;
   }

   public int getWeight() {
      return weight;
   }

   public String says() {
      return "An animal can't talk!";
   }
}

class Cow extends Animal {
   public String says() {
      return "Moo";
   }
}

class Pig extends Animal {
   public String says() {
      return "Grunt";
   }
}


Dit gegeven, zou ik het volgende kunnen doen, waarna de variabele animal refereert naar dezelfde geheugenplek als de variabele daisy.
Java:
1
2
Cow daisy = new Cow();
Animal animal = daisy;

Heel leuk allemaal, maar... wat heb ik er aan???
Ik heb zojuist een variabele van de klasse Animal gemaakt die wijst naar een Cow. Als ik eigenschappen van die Cow wil gebruiken dan neem ik toch de variabele daisy?

Heeft iemand hier een heldere kijk op?

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

code:
1
2
3
4
class Zoo
{
  private Animal[] beestjes;
}


dat heb je eraan

daarenboven, zal
beestjes[0].says()
als return "Moo" hebben als
beestjes[0] = new Cow("blaar")

[ Voor 39% gewijzigd door H!GHGuY op 08-06-2005 20:55 ]

ASSUME makes an ASS out of U and ME


  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
Java Collections, van voor de 1.5 compiler, retourneerde Object referenties, zodat je alle type classen in de container kon opslaan. Als je vervolgens iets uit de container haalt, dan zul je het object weer moeten 'upcasten'. Verder zijn algemene types generalisaties en weet je niet altijd welk type je binnen krijgt.

Er zijn nog veel meer gedetailleerde regeltjes en gebruiken, maar ik denk dat je hiermee voor je begrip wel even voldoende hebt. ;)

[ Voor 36% gewijzigd door Glimi op 08-06-2005 20:54 ]


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

Alarmnummer

-= Tja =-

cbijlsma schreef op woensdag 08 juni 2005 @ 20:49:
Geachte medetweakers,
Heel leuk allemaal, maar... wat heb ik er aan???

Ik heb zojuist een variabele van de klasse Animal gemaakt die wijst naar een Cow. Als ik eigenschappen van die Cow wil gebruiken dan neem ik toch de variabele
Het probleem is dat je niet altijd weet welke class je krijgt. Stel dat je een boerderij hebt en je wilt dat alle dieren geluid gaan maken. Dan zou je ieder dier op je boerderij een schop kunnen geven, ongeacht het soort.

code:
1
2
3
4
5
void schop(){
   for(int k=0;k<dieren.length;k++){
      System.out.println( dieren[k].says());
   }
}


Hierin ligt de kracht van oo.. Jij kunt nu allerlei nieuwe dieren op je boerderij plaatsen, olifanten, wormen kippen etc. Maar jou schop functie die werkt nog steeds perfect.

[ Voor 3% gewijzigd door Alarmnummer op 08-06-2005 20:58 ]


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

Alarmnummer

-= Tja =-

Glimi schreef op woensdag 08 juni 2005 @ 20:53:
Java Collections, van voor de 1.5 compiler, retourneerde Object referenties, zodat je alle type classen in de container kon opslaan. Als je vervolgens iets uit de container haalt, dan zul je het object weer moeten 'upcasten'. Verder zijn algemene types generalisaties en weet je niet altijd welk type je binnen krijgt.

Er zijn nog veel meer gedetailleerde regeltjes en gebruiken, maar ik denk dat je hiermee voor je begrip wel even voldoende hebt. ;)
Dit geld uiteraard niet voor arrays. Arrays waren voor 1.5 de enigste geparametriseerde type in java.

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 22-03 18:12
Dat is handig is je voor een Cow instantie toch de functionaliteit van Animal wilt gebruiken (en verder wat hierboven wordt vertelt natuurlijk). Je kunt ook:
code:
1
((Animal)daisy).says();

doen. Dan roep je dus met de data van daisy een message in Animal aan.

Noushka's Magnificent Dream | Unity


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

Alarmnummer

-= Tja =-

Michali schreef op woensdag 08 juni 2005 @ 20:57:
Dat is handig is je voor een Cow instantie toch de functionaliteit van Animal wilt gebruiken (en verder wat hierboven wordt vertelt natuurlijk). Je kunt ook:
code:
1
((Animal)daisy).says();

doen. Dan roep je dus met de data van daisy een message in Animal aan.
Hmmm.. ik weet het niet zeker, maar ik denk niet dat deze vlieger opgaat. Volgens mij kan je van buitenaf nooit forceren dat je van een superclass zijn implementatie gebruik gaat maken. Dat zou namelijk extreem gevaarlijke situaties opleveren.

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 22-03 18:12
Alarmnummer schreef op woensdag 08 juni 2005 @ 21:13:
[...]


Hmmm.. ik weet het niet zeker, maar ik denk niet dat deze vlieger opgaat. Volgens mij kan je van buitenaf nooit forceren dat je van een superclass zijn implementatie gebruik gaat maken. Dat zou namelijk extreem gevaarlijke situaties opleveren.
Maar als je dan iets als dit doet:
code:
1
2
Animal animal = (Animal)daisy;
animal.says();

Maak je dan met de method call nog steeds gebruik van Cow of wordt dan wel Animal gebruikt?

niet dat ik het ooit nodig heb ;)

[ Voor 5% gewijzigd door Michali op 08-06-2005 21:17 ]

Noushka's Magnificent Dream | Unity


  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
Alarmnummer schreef op woensdag 08 juni 2005 @ 21:13:
Hmmm.. ik weet het niet zeker, maar ik denk niet dat deze vlieger opgaat. Volgens mij kan je van buitenaf nooit forceren dat je van een superclass zijn implementatie gebruik gaat maken. Dat zou namelijk extreem gevaarlijke situaties opleveren.
Het klopt wat je hier zegt. Het casten naar een superclass betekent niet dat de superclass implementatie gebruikt gaat worden Er is namelijk geen verschil tussen het direct casten en een gecaste instantie terug krijgen uit een method.
Java:
1
2
Animal a = (Animal) daisy;
String s = a.says();

en
Java:
1
2
3
4
5
6
7
public Animal castToAnimal( final Cow p_cow ) {

  return (Animal) p_cow; // cast eigenlijk redundant
}

Animal a = castToAnimal( daisy );
String s = a.says();

Verwijderd

Als ik de vraag van de TS interpreteer als "Wat is het nut van een expliciete cast?", dan is het antwoord dat het meestal gebruikt word om om fouten/onvolkomendheden in het type systeem van java zelf heen te werken, of om design fouten in je eigen code te verbloemen.

Het nut van polymorphisme/late binding staat hier natuurlijk los van. Dat is een basisprincipe van het OO denken.

Meer concreet, de meeste casts worden impliciet door de taal zelf gedaan. Heb je een functie die een Base verwacht, dan mag je deze gewoon een Sub meegeven. Hierbij is de cast van Sub naar Base implciet.

Kijk je echter naar de oude collection classes, dan stopte je hier een Object in en moest je bij het eruithalen zelf maar aangeven wat het was. Dit was een fout in het type systeem van Java wat met 1.5 eindelijk is gefixed.

Ik ben zelf ook wel geintesseerd in situaties waar een cast echt in een valide situatie nodig was.
De enige situatie die ik zelf ben tegengekomen is de volgende:

1) Je hebt een interface X die een high level data object voorsteld en een interface Y die een pluggable handler/processor voor X voorstelt.
2) Een implementatie van X en een implementatie van Y horen bij elkaar in een paar.
3) Het systeem krijgt objecten binnen van type X (en roept functies hierop aan volgens de interface X) en stuurt deze door naar de pluggable handler Y die het alleen via de interface Y kan benaderen.
4) Omdat de handler Y implementatie specificieke dingen kan gebruiken van X, doet Y een down-cast naar het werkelijke type van X en gooit een runtime exception als dit niet lukt.

Ik kan er naast zitten, maar volgens mij is er geen methode om dit in Java uit te drukken zonder de down-cast te doen.

  • coenbijlsma
  • Registratie: Augustus 2004
  • Niet online
Alarmnummer schreef op woensdag 08 juni 2005 @ 20:56:
[...]

Het probleem is dat je niet altijd weet welke class je krijgt. Stel dat je een boerderij hebt en je wilt dat alle dieren geluid gaan maken. Dan zou je ieder dier op je boerderij een schop kunnen geven, ongeacht het soort.

*knip*
Ik denk dat dit al heel goed weergeeft waarom ik zo'n classcast omhoog zou willen. Je kunt dan inderdaad doen wat HIGHGuy ook zegt:
HIGHGuY schreef op woensdag 08 juni 2005 @ 20:53:
code:
1
2
3
4
class Zoo
{
  private Animal[] beestjes;
}


dat heb je eraan

daarenboven, zal
beestjes[0].says()
als return "Moo" hebben als
beestjes[0] = new Cow("blaar")
Zo hoef je dus maar 1 aanroep te doen:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ArrayList beestjes = new ArrayList();

// Er even vanuit gaan dat ik de ArrayList gevuld heb..
for(int n = 0; n < beestjes.size(); n++) {
   if(beestjes.get(n) instanceof(Animal)) {
      String s = (Animal)beestjes.get(n).says();
   }
}

// IN PLAATS VAN
for(int n = 0; n < beestjes.size(); n++) {
   if(beestjes.get(n) instanceof(Cow)) {
      String s = (Cow)beestjes.get(n).says();
   }
   if(beestjes.get(n) instanceof(Pig)) {
      String s = (Pig)beestjes.get(n).says();
   }
   // enz..
}


@ henk_DE_man:
Verwijderd schreef op woensdag 08 juni 2005 @ 21:42:
Als ik de vraag van de TS interpreteer als "Wat is het nut van een expliciete cast?",
*knip*
Dat was niet helemaal m'n bedoeling, maar het helpt wel om dit iets beter te begrijpen ;)

En tenslotte nog @Michali:
Michali schreef op woensdag 08 juni 2005 @ 21:16:
[...]

Maar als je dan iets als dit doet:
code:
1
2
Animal animal = (Animal)daisy;
animal.says();

Maak je dan met de method call nog steeds gebruik van Cow of wordt dan wel Animal gebruikt?

niet dat ik het ooit nodig heb ;)
Volgens mij wijst animal na je actie naar hetzelfde geheugenadres als daisy (Dus een Cow).
Pagina: 1