Verwijderd schreef op 17 juni 2004 @ 20:54:
[...]
Bingo! Volgens mij hebben we hier de hele clue van het verhaal. Jij bent wel thuis in de informatica, maar meer op een hoger niveau. Je hebt je waarschijnlijk nog niet of weinig bezig gehouden met hoe zulke dingen op machine niveau geimplementeerd worden.
Wel, maar ik accepteer het niet.

En ik ga niet roepen dat ik dat zelf maar aan ga passen oid (in een of andere high-level taal oid), omdat ik dat mogelijk (

) niet kan, en omdat dat raar over komt.
Bovendien; waarom is iets onconventioneels als reflection wél mogelijk, maar dit aspect daaraan
niet?

Ik denk dat als Sun hier voor te porren is (MS heeft het ook

) dat ze deze functionaliteit wel toevoegen.
Maar
(nee .oysin, ik ben het niet vergeten
) is dit niet mogelijk dmv die
dynamic proxies in
Java? Misfire ontkende dat, zoals ik al zei, bijzonder overtuigend.
Maar goed, als niemand het kan zeggen, dan zal ik het wanneer ik tijd heb eens proberen.

Als je naar de memory layout en vtable van een class kijkt, dan is het opvatten van een pointer van het ene type als een pointer van het andere type precies het zelfde als wanneer dat eerste type 'officieel' zou zeggen dat het ook dat andere type is.
Precies, dat begrijp ik ook wel, ik ben qua "machinale" talen een frequent beoefenaar van assembly.

Maar wat is de vtable?

Is dat het definitiegedeelte (fields, methods, etc) van een class zoals C deze spiegelt in het geheugen?
Tenminste... voorzover de memory layout toevalligerwijs overeenkomt. Als dat zo is heb je geluk, maar je hebt niet die garantie. Zie mijn bovenstaande voorbeeld waar ik 2 compleet ongerelateerde classen naar elkaar cast, en waar dat (toevallig) goed gaat.
Maar dat gaat niet op voor een "class" versus een "Class"...
Wat op zich geen ramp zou moeten zijn, als Class voldoende functionaliteit zou bevatten om ook mijn vraagstuk te realiseren.
Ik denk dat het heel belangrijk is voor deze discussie dat je dat begrijpt. Als je vanuit de functionele hoek komt is het mischien even een gedachten twist die je moet maken. (Ik weet nog dat ik een zelfde soort twist moest maken toen ik voor het eerst wat met functionele en logische talen moest doen).
Ja, gelukkig heb ik me éérst verdiept in imperatieve talen. Maar deze zijn ook wat meer praktisch gericht, en mijn activititeiten qua functioneel programmeren zijn hooguit hobbyisme,
offtopic:
Maar om ff offtopic te zijn (mag ik ook wel ff nu he?

): ik heb er daar ooit eens over nagedacht, en ik zag de discussies over het nut van threads (zoals gebruikt in imperatieve talen) al voor me...
Want als je programmeert met bijv. de
Lambda Calculus, kunnen deze "stromen" gesymboliseert als "threads", compile-time worden bepaald...
Behalve als je polymorfe code hebt natuurlijk, maar ja, volgens mij is dat niet echt de bedoeling van een niet-machinale taal...
Dan moet je het morferingsproces als een soort bacteriedeling opvatten, waarbij de 1e bacterie de oude binary is, en de 2e de nieuwe. En de oude sterft dan af later natuurlijk...
Zo zie je maar weer, komt toch heel wat bij kijken, die verschillen in talen\inzichten.

Wat zou Edsger Dijkstra of Donald Knuth er van vinden...

Een object opvatten als het type van een interface is dus heel sterk wel relevant en heeft ook nix te maken met het instantiaten van een interface (wat dus niet kan).
Dat snap ik, maar hoe wil je
Java dat laten doen...
Mischien dat 2 simpele illustraties een beetje helpen. Stel je 2 classen voor die allebei 3 gelijknamige data members hebben, 1 int, een char en nog een 1.
In het geheugen staat die mischien als
class 1:
$[allocation address]
+ 0 : 32 bits (integer a)
+ 4 : 8 bits (char b)
+ 5 : 32 bits (integer c)
class 2:
$[allocation address]
+ 0 : 32 bits (integer a)
+ 4 : 8 bits (char b)
+ 5 : 32 bits (integer c)
De addressen en types komen precies overeen. Stel je hebt een pointer naar class 1 op address $1000. Als je nu tegen de compiler zegt dat je integer c wilt vullen met 50 dan komt er ongeveer in pseudo machine code iets te staan als:
store $1000+5, #50
Als je nu tegen de compiler 'liegt' en zegt dat op address $1000 geen object van classe 1 staat, maar van classe 2, en je wilt vervolgens van classe 2 integer c vullen, dan gaat het in dit simpele geval goed. Er wordt namelijk precies dezelfde machine code voor gegenereerd. IHA heb je deze garantie echter niet.
Als je nu een pointer (in java) naar een interface zou casten, dan genereerd de compiler precies die code alsof het object op die plaats in het geheugen -wel- die interface had geimplementeerd. -Als- de layout en vtable (of java's equivalent daarvan) precies overeenkomen dan gaat dat dus goed, anders gaat het gruwelijk fout. C en C++ programmeurs nemen soms deze verandwoordelijkheid.
De compiler kan dit echter niet controleren, dus is het niet toegestaan in Java. In java mag je niet rommelen met pointers. Daarom stelde ik ook dat enkel conceptueel de reinterpret_cast precies zou doen wij jij wilde. Uit .oisyn's post van Thursday 17 June 2004 18:05 blijkt dat dat ook inderdaad zo is.
Je zegt nu precies wat ik stelde in mijn reactie op jou...

[...]
Functioneel gezien is het een safe cast, maar practisch gezien hoeft dat helemaal niet zo te zijn. -Alleen- als de compiler voor de interface en het object dezelfde vtable genereerd zou het werken. Dit valt echter buiten de language spec, en is dus undefined behaviour. Als het op jouw compiler werkt is dat toevallig.
Volgens mij werkt de JVM niet zo low-level, aangezien er in de byte-code toch geen expliciete pointers voor komen, zal hij alles dynamisch moeten alloceren.
Maar de objecten zijn dus feitelijk identiek qua memory layout (want hun types zijn dat ook), alleen de offsets in het geheugen niet. Maar aangezien een cast over types gaat, zou dat niet uit moeten maken.
Oh, voor als je niet weet wat een vtable is, heel simpel gezegd: een array met verwijzingen naar functies die runtime (achter de schermen) doorlopen wordt om mbt polymorfisme de juiste functie implementatie te vinden.
Hmm, zegt me vrij weinig, aangezien ik de context van C++ niet ken (die linking en die scrupules met entry points van libraries etc. vormen juist mijn grote afkeer van C++

).
[...]
Het heeft ook niks te maken met of C++ of Java hetzelfde zijn, of compatible of niet, het gaat om de concepten.
Daar spreek ik standaard over.

Ook in java in conceptueel gezien een interface inheritance. Ook in java heb je pointers. Sterker nog, je hebt in java alleen maar heap gealloceerde objecten, en dus alleen maar pointers. Java heeft ook geen call bij reference semantics, maar alleen call by value: pointers worden by value doorgegeven, etc, etc. Dat de dingen anders heten betekent niet dat de concepten verschillen.
Jaa, maar dat klopt ook wel, echter
Java staat mij niet toe daarmee te tamperen, dus ik heb weinig aan het concept.

[...]
Heeft deze comment nou betrekking op mijn code sample of op jouw code? Wat ik opschreef is gewoon standaard java hoor. Als je een pointer naar een base hebt in Java kun je gewoon naar een van de feitelijke types casten.
Op jouw code, maar ik ken al die types dus niet compile-time, dat is het punt.
Hier komt al om de hoek kijken dat een interface implementen hetzelde is als inheritance, want via de
instanceof operator en de cast maakt
Java geen enkel onderscheid tussen beiden.
Bv
Java:
1
2
3
4
5
| if (base instanceof ISomething)
// ....
if (base instanceof Sub)
// .... |
Tevens je instantieert ook hier niet een interface: je maakt een instantance van een class (dat kun je, had je eerder gezegd), en die instance cast je naar het type van de interface.
Nu je het zegt, dit zou dan inderdaad moeten kunnen. Echter, probleempje: ik kan niet casten naar een Class(Type)-object, alleen naar een class (type).

[...]
Dat is wel het allerbelangrijkst, en in een van mijn eerste posts in deze thread had ik je ook al hierna gevraagt (maar je gaf geen antwoord hierop). Echter, -waar- is het type van de Interface onbekend?
Overal buiten de scope van de interface zelf.
Iniedergeval dus op de plek waar je class de interface zou moeten implementeren, maar ook op de plek waar je de ingelade code gaat gebruiken?
Juist. Ik denk dat er een misverstand onstaan is, ik laad die Classes dus niet voor m'n lol met die ClassLoader, anders had ik uiteraard wel met dat casten ed aan de gang gegaan. Zoals ik al zei: ik doe
al mijn imports met die ClassLoader, op de standaard
Java libraries na. Ik weet dat dit niet erg goed is voor de performance, maar de truuk is dat deze classes op zich (kunnen) staan, en ik dus vrijwel geen invoke()s ed hoef te doen via
Java reflection op de instantie(s) van deze classes.
Er zal toch ooit ergens in de code een plek moeten zijn waar iemand de interface wel kent. Stel namelijk dat in de gehele code base nergens de interface bekend is, dus niet in de classes die je dynamisch laadt als plug-in, en niet in de code die dat laden uitvoert, dan heb je toch ook nergens die interface nodig?
Hehe, dat is al eerder ter sprake gekomen, dat is dus wel zo, want
ik ken die interface dus wel, en
ik weet dat ik hem ergens wil gebruiken.

Nou, duidelijk is dat dus niet zo, dus er komt ergens een plek die de interface wel kent. Nou, op dat moment kun je dus die denkbeeldige java reinterpret_cast doen.
Helaas...

[...]
Check net pas je profiel en blijkt dus student HBO-IN te zijn. Kwa vraagstelling enzo zat ik eigenlijk aan een student van de universiteit nijmegen te denken

offtopic:
Laat ik nou nét van plan zijn daar te gaan studeren. /-\o_

/-\o_
Maar in welk opzicht? Als men zich daar in de regel ook niet blind staart op de meest voor de hand liggende mogelijkheden van bestaande programmeertalen dan komt mij dat goed uit...

[
Voor 3% gewijzigd door
Verwijderd op 17-06-2004 21:46
]