Black Friday = Pricewatch Bekijk onze selectie van de beste Black Friday-deals en voorkom een miskoop.
Toon posts:

[JAVA] Implementen van een Interface d.m.v. reflection?

Pagina: 1 2 Laatste
Acties:
  • 461 views sinds 30-01-2008
  • Reageer

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 14-11 23:57

.oisyn

Moderator Devschuur®

Demotivational Speaker

Matched: proxy, java
Cybarite: ik heb een stuk toegevoegd aan mijn vorige post wat voor jou denk ik wel van belang is (nofi dat ik over je praatte in de 3e persoon, ik had het immers tegen Henk ;)). Ik gebruikte de C++ code om het uit te leggen aan Henk, aan casts heb jij weinig omdat je in java niet zomaar met pointers kunt werken.

Ik heb verder geen verstand van die InvocationHandler van java, maar je moet het ongeveer zo zien:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class MyClass implements java.lang.reflect.InvocationHander
{
    // functies van MyInterface
    void func1 () { System.out.println ("func1"); }
    void func2 () { System.out.println ("func2"); }

    void invoke (String name, Object[] params)
    {
        if (name.equals ("func1"))
            func1 ();
        else if (name.equals ("func2"))
            func2 ();
    }
}


Let wel, dit is dus niet letterlijk de manier waarop InvocationHandler echt werkt, maar puur om je een idee te geven hoe het ongeveer in elkaar zit :)

Het idee is vervolgens dat je je MyClass laadt met een classloader, en dan een Proxy vanuit code aanmaakt die MyInterface implementeert en je MyClass instantie gebruikt om de calls naar door te sluizen

[ Voor 10% gewijzigd door .oisyn op 17-06-2004 18:22 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Matched: dynamic, java
Verwijderd schreef op 17 juni 2004 @ 18:00:
[...]


Ik heb zojuist de nieuwe posts doorgelezen, maar die zijn allemaal ietwat offtopic. B)

Ik kan weinig casten, aangezien ik een Interface implement, en geen abstract class extend. Verder zou ik niet weten hoe ik een reinterpret_cast kan uitvoeren als ik het over het implementen van een Interface heb...
Kijk! :) Dan zijn de nieuwe posts (sommige dan), toch minder off topic als je denkt. Namelijk, een interface is eigenlijk niets anders dan inheritance van een pure abstracte base class.

Ik heb een groot vermoeden dat jij gewoon de term "interface laten implementeren" verkeerd gebruikt. Namelijk, je zei ergens hierboven dat de class (en dus ook het object van die class) de benodigde methoden al had geimplementeerd. Met de term "interface laten implementeren" denken veel mensen dat je at runtime methodes aan een class wilt gaan toevoegen. Dat is dus duidelijk niet de bedoeling.

Wat je dus (als ik het goed heb) bedoelt, is dat een object alleen maar opgevat hoeft te worden als het type van een interface. Dit is precies wat een cast doet. De gewone c-style cast kijkt in de class definitie of een cast mag. Dit mag als het target type in de inheritance-chain voorkomt, of in een van de geimplementeerde interfaces. Conceptueel is een interface ook gewoon inheritance, maar dan alleen van een type.

Bv

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
public class Base {

    public void something() {}

}

public interface ISomething {
    public void something();
}

public class Sub extends Base implements ISomething {

    public void something() {}

}

// in some function of some class
void f() {

    Base base = new Sub();
    
    ISomething iSomething = (ISomething) base; // cast
    Sub sub = (Sub) base; // cast

}


Zoals je boven ziet doe je dus in beiden gevallen een cast om een pointer naar Base als een ISomething of als een Sub te beschouwen. Dit is equivalent met wat in andere talen wel een dynamic cast wordt genoemt.

Aanschouw nu de volgende code sequentie:


Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Base {
    public void something() {}
}

public interface ISomething {
    public void something();
}

public class Sub extends Base /*implements ISomething 'vergeten' */ {
    public void something() {}
}

// in some function of some class
void f() {

    Base base = new Sub();
    
    ISomething iSomething = (ISomething) base; // cast, not allowed right now
    Sub sub = (Sub) base; // cast

}


De cast is nu niet toegestaan omdat je de compiler niet hebt verteld dat je dit wilt toestaan. In jouw hypothetische geval was het dus een kwestie van niet kunnen vertellen.

Nu komt de reinterpret cast om de hoek kijken. Bij het gebruik van dezelfde classes, een nieuwe f functie:

C++:
1
2
3
4
5
6
7
8
void f() {

    Base* base = new Sub();
    
    ISomething iSomething = reinterpret_cast<ISomething*>( base); // cast enforced
    Sub* sub = (Sub*) base; // cast

}

Verwijderd

Topicstarter
Matched: dynamic, proxy, java
.oisyn schreef op 17 juni 2004 @ 18:05:
Wat hier moet gebeuren is het aanmaken van een proxy, die MyInterface implementeert en de calls doorsluist naar een MyClass.
Daar zou ik best mee kunnen leven ja, maar misfire schoot het idee van iemand over een dynamic proxy eerder al vrij overtuigend af. ;)
Waarom Cybarite dit probleem heeft is me niet helemaal duidelijk, maar ik heb een vermoeden dat MyClass een soort van plugin is die via een classloader wordt ingeladen.
Je slaat de spijker op z'n kop, dit probleem haalde ik mezelf op de hals en daarom zei ik al dat ik het allang heb opgelost. Blijft echter wel dit interessante vraagstuk open staan.
En inderdaad, alles wordt via een ClassLoader geladen (kan geen (relevante) imports doen, zei ik al eerder).
En bij het implementeren van de plugin heeft hij geen beschikking over de interfaces die geimplementeerd moeten worden (maar als persoon heeft ie er natuurlijk wel kennis over).
Precies, maar voor alle duidelijkheid: ik kan dus wel instances van MyClass maken.
Ik denk dat een oplossing door een Proxy toch het beste is. Wat hij dan wel moet doen is zorgen dat MyClass een InvocationHandler implementeert (hetzelfde als de IDispatch waar curry het over had), en dus in de invoke () methode de calls doorsluist naar de juiste methode. Op die manier is bij het implementeren van MyClass de MyInstance niet nodig.
Hoe bedoel je de calls doorsluist?
Als MyClass hier in feite 'MyInterface' is, kun je toch niks doorsluizen?
Want dat is waar jullie het net over hadden, dan ga je zelf implementations toevoegen/de definitie van de Interface niet strikt navolgen (extra methoden)...
Of geldt dit niet als die methoden private/protected zijn?
Of dat ik gewoon een 'meta'-class maak, die de communicatie tussen MyInterface en MyClass verzorgt? Maar dan moet bij één van beiden de definitie van MyInterface wel bekend zijn...
Ik kan dan ook een kunstmatig raakvlak maken van beide 'classes' (waarvan één Interface dus), zodat beiden weten welke methode ze kunnen aanroepen om met elkaar te communiceren?
Dit stukje twijfel ik nog over, ik heb dus wel een MyInstance (van MyClass).
Maar de 'MyInterface' heb ik dus niet volgens de JVM....
InvokeHandler natuurlijk wel, maar dat is een standaard java klasse en dat moet dus geen probleem zijn lijkt me. En als dat wel een probleem is dan heeft ie vet pech, want dan is er gewoon geen oplossing zonder byte-code generation :Y)
Hehe, zeker niet, want als ik de standaard Java libraries niet kon importen is het onmogelijk om de applicatie te kunnen laten draaien (ook niet via ClassLoaders ;)). :D

edit:
Ik kreeg de indruk dat er een definitieverwarring is over MyClass en MyInterface, dus ik houd met beide begrippen rekening in m'n reactie. Ik heb je code niet meer bekeken dus later corrigeer ik wellicht nog het eea, maar ik moet nu eerst ff op Henk reageren. :+

[ Voor 7% gewijzigd door Verwijderd op 17-06-2004 18:47 ]


Verwijderd

Topicstarter
Matched: java
Verwijderd schreef op 17 juni 2004 @ 18:34:
[...]


Kijk! :) Dan zijn de nieuwe posts (sommige dan), toch minder off topic als je denkt. Namelijk, een interface is eigenlijk niets anders dan inheritance van een pure abstracte base class.
Dat weet ik, en ik zeg later ook dat me nog onduidelijk is hoe Java dat afhandelt...
Ik zie Java (de compiler dan) er best voor aan dat ze hier kunstmatig restricties aan opleggen, om de iedere indruk weg te nemen dat een interface niets meer is dan een volledig abstracte class... :|
Ik heb een groot vermoeden dat jij gewoon de term "interface laten implementeren" verkeerd gebruikt. Namelijk, je zei ergens hierboven dat de class (en dus ook het object van die class) de benodigde methoden al had geimplementeerd. Met de term "interface laten implementeren" denken veel mensen dat je at runtime methodes aan een class wilt gaan toevoegen. Dat is dus duidelijk niet de bedoeling.
Hehe, daarover zal best verwarring zijn ontstaan ja, maar ik zeg vrij duidelijk wat ik wil inclusief het feit dat ik al deze methoden al heb geimplement in m'n code van de class, maar dat het slechts om een formaliteit gaat wat betreft het 'implements'-keyword in Java waardoor Java de Interface in kweste ook daadwerkelijk officieel laat implementen. Als iedereen gewoon secuur leest wat ik zeg, en er zelf niets bijdenkt dan zou je men niet verward zijn. :)
Wat je dus (als ik het goed heb) bedoelt, is dat een object alleen maar opgevat hoeft te worden als het type van een interface.
Nee, dat is niet relevant, aangezien ik een Interface toch niet los kan instantiaten, zoals iemand al opmerkte. Het gaat me er om dat die Interface officieel geimplement moet worden door een bepaald Object. En dus dit Object genotificeerd wordt van Events die optreden binnen de Interface, waarvoor de Interface dus meestal wordt gebruikt. ;)
(Dit om het verhaal even compleet te maken. :))
Dit is precies wat een cast doet. De gewone c-style cast kijkt in de class definitie of een cast mag. Dit mag als het target type in de inheritance-chain voorkomt, of in een van de geimplementeerde interfaces.
Precies, maar aan die voorwaarden kan (offcieel) niet worden voldaan. Toch is het een safe cast, maar dat weet alleen de programmeur.
Het is ook niet dat ik willekeurige parameters accepteer voor deze operatie oid, ik werk met ClassLoaders, en geef hard op over welk type(s) ik het heb. Feitelijk dus net zo veilig als conventionele Java-syntax, maar dat kan de (huidige) compiler natuurlijk niet controleren....
Conceptueel is een interface ook gewoon inheritance, maar dan alleen van een type.
Dan ga je C++ en Java door elkaar gooien. Deze vergelijking klopt wel, maar is praktisch niet erg veelbetekenend aangezien Java en C++ wat dit betreft niet compatible zijn, en dat ook niet zijn te maken. Dus jij weet wat het synoniem zou kunnen zijn van een bepaalde logische constructie van C++ onder Java, maar dat kun je Java natuurlijk niet aan het verstand peuteren.
Bv

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
public class Base {

    public void something() {}

}

public interface ISomething {
    public void something();
}

public class Sub extends Base implements ISomething {

    public void something() {}

}

// in some function of some class
void f() {

    Base base = new Sub();
    
    ISomething iSomething = (ISomething) base; // cast
    Sub sub = (Sub) base; // cast

}
Heel nifty ja, maar helaas kan ik die Interface met geen mogelijkheid instantieren....
Dit zou niet kunnen in Java, zo heb ik dus vernomen (wederom een kunstmatige restrictie uit purisme van de eigen definitie).
En last but not least, het type van de Interface is mij dus officieel onbekend!
Maar de Java reflection API kan zogezegd naast voorzien in een ClassLoader-functionaliteit, ook de Fields ed van een ingeladen class/type exporteren. Mijn vraag is dus of dit het dynamisch officieel implementen van Interfaces mogelijk maakt.
Aanschouw nu de volgende code sequentie:


Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Base {
    public void something() {}
}

public interface ISomething {
    public void something();
}

public class Sub extends Base /*implements ISomething 'vergeten' */ {
    public void something() {}
}

// in some function of some class
void f() {

    Base base = new Sub();
    
    ISomething iSomething = (ISomething) base; // cast, not allowed right now
    Sub sub = (Sub) base; // cast

}


De cast is nu niet toegestaan omdat je de compiler niet hebt verteld dat je dit wilt toestaan. In jouw hypothetische geval was het dus een kwestie van niet kunnen vertellen.

Nu komt de reinterpret cast om de hoek kijken. Bij het gebruik van dezelfde classes, een nieuwe f functie:

C++:
1
2
3
4
5
6
7
8
void f() {

    Base* base = new Sub();
    
    ISomething iSomething = reinterpret_cast<ISomething*>( base); // cast enforced
    Sub* sub = (Sub*) base; // cast

}
Enforcen... maar wat?
Probleem is niet alleen dat Java me dit niet toestaat, ik heb gewoon het type niet...
Ik weet nogmaals niet of er een class Interface in de Java reflection API bestaat, maar als zou dat zo zijn, dan is dat nog niet het equivalent van een interface... (met kleine I dus).

Als dat wel zo was, zou dit namelijk moeten werken:
Java:
1
2
Class Klasse = Class.forName("net.tweakers.forum.PEnW");
Klasse subforum = new PenW();

In dit voorbeeld heb ik expres "Klasse" gebruikt.
Want dit bewijst dus dat Klasse in feite classObject is, en subforum een classObjectInstance....

Ze zijn dus niet uitwisselbaar met het conventionele type class en interface (is ook niet zo onverwacht ;)), en aan casten heb ik dus vrij weinig.

Tja, if only Java had explicit pointers... >:)
Dan zou ik wat 'dirty' werk niet schuwen hoor. :)


edit
Als mijn studiejaar is afgerond (na volgend weekend, als ik daarna geen tijd weet te vinden over een ruime week) zal ik hier eens meer over uitzoeken net als nog wat gevaarlijke truucjes die ik ondertussen al heb bedacht, vooral rond abstracte classes... >:)

[ Voor 6% gewijzigd door Verwijderd op 17-06-2004 19:23 . Reden: post scriptum ]


Verwijderd

Matched: java
Verwijderd schreef op 17 juni 2004 @ 19:17:

[...]
maar dat het slechts om een formaliteit gaat wat betreft het 'implements'-keyword in Java waardoor Java de Interface in kweste ook daadwerkelijk officieel laat implementen.

[Wat je dus (als ik het goed heb) bedoelt, is dat een object alleen maar opgevat hoeft te worden als het type van een interface.]

Nee, dat is niet relevant, aangezien ik een Interface toch niet los kan instantiaten, zoals iemand al opmerkte.

Het gaat me er om dat die Interface officieel geimplement moet worden door een bepaald Object.
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.

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

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

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

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.
Precies, maar aan die voorwaarden kan (offcieel) niet worden voldaan. Toch is het een safe cast, maar dat weet alleen de programmeur.
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.
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.
[Conceptueel is een interface ook gewoon inheritance, maar dan alleen van een type.]

Dan ga je C++ en Java door elkaar gooien. Deze vergelijking klopt wel, maar is praktisch niet erg veelbetekenend aangezien Java en C++ wat dit betreft niet compatible zijn, en dat ook niet zijn te maken.
Het heeft ook niks te maken met of C++ of Java hetzelfde zijn, of compatible of niet, het gaat om de concepten. 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.
Heel nifty ja, maar helaas kan ik die Interface met geen mogelijkheid instantieren....
Dit zou niet kunnen in Java, zo heb ik dus vernomen (wederom een kunstmatige restrictie uit purisme van de eigen definitie).
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.

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.
En last but not least, het type van de Interface is mij dus officieel onbekend!
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?

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?

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?

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.
Als mijn studiejaar is afgerond (na volgend weekend, als ik daarna geen tijd weet te vinden over een ruime week)
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 :)


zal ik hier eens meer over uitzoeken net als nog wat gevaarlijke truucjes die ik ondertussen al heb bedacht, vooral rond abstracte classes... >:)[/quote]

Verwijderd

Topicstarter
Matched: dynamic, java
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 (:P) 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 :P) 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? :P): 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... :o
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). :p
[...]


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_ :D /-\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... B)

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


Verwijderd

Matched: dynamic, java
Verwijderd schreef op 17 juni 2004 @ 21:40:
[...]

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 (:P) niet kan, en omdat dat raar over komt.
Sommige concepten, zoals memory layout en eigenlijk het hele imperatieve model komen gewoon rechtstreeks voort uit de opbouw van de machine. Java wordt in 99% van de gevallen naar dezelfde machine gecompileert; de JVM. Deze is weliswaar meestal virtueel, maar volgt nog steeds het Von Neumann model. Het mapt dan ook redelijk naar de huidige computer architecturen. Soms zelfs een beetje -te- direct. In de JVM zijn variable reads en writes atomair, behalve voor Doubles. Dit vanwege mappings naar een echte machine.
Precies, dat begrijp ik ook wel, ik ben qua "machinale" talen een frequent beoefenaar van assembly. ;)
Juist ja... ergens geloof ik het niet helemaal ;)
[...]
Maar dat gaat niet op voor een "class" versus een "Class"...
Ik snap niet helemaal wat je met class vs Class bedoelt. Kwa data members geldt het echter voor alles wat maar een memory layout heeft.

In C++ kun je bv een object 'met de hand' in een leeg stukje geheugen opbouwen.

Bv, hier een vb. (kenners van de win32 API herkennen dit wel :) )

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
BYTE* pData ;
RGNDATA* pRgnData ;
RECT* pRect ;
                    
// create RGNDATA structure 'manually'
pData = new BYTE[ sizeof( RGNDATAHEADER ) + sizeof( RECT ) * iCount ];      
pRgnData = ( RGNDATA* )pData ;

// first element of RECT array
pRect = ( RECT* )( pData + sizeof( RGNDATAHEADER ) ) ;
                    
// set fields of header
pRgnData->rdh.dwSize    = sizeof( RGNDATAHEADER  ) ;
pRgnData->rdh.iType     = RDH_RECTANGLES ;
// ...
Dat snap ik, maar hoe wil je Java dat laten doen...
Ik zou het iniedergeval niet weten. Het was voornamelijk bedoelt als voorbeeld om er achter te komen wat je nu precies bedoelde. Het begint langzamerhand een beetje duidelijk te worden nu :)
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.
Bytecode is redelijk assembly-like hoor, en werkt dus wel zeer zeker expliciet met 'pointers'. Om dit niveau worden dat echter geen pointer genoemt, maar valt het onder een addressing mode zoals bv Register deferred of indirect.
Maar de objecten zijn dus feitelijk identiek qua memory layout (want hun types zijn dat ook), alleen de offsets in het geheugen niet.
Als 2 classes dezelfde memory layout voorschrijven dan hebben objecten van die classes ook precies dezelfde offset tov het address van de pointer. Het bepalen van welke offset welke data member heeft IS namelijk wat de memory layout bepaalt. :)

In C++ werkt het overigens iets gecompliceerder, omdat je verschillende base classen kunt hebben, en er natuurlijk maar eentje op offset 0 van address waar de pointer naar verwijst kan beginnen.
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 nix met entry points in libs te maken. Standaard C++ kent ook het begrip dynamic/shared library helemaal niet. Dat zijn altijd platform extensies.

De vtable zorgt ervoor dat je language runtime weet welke functie hij moet aanroepen voor een object. Voor gewone functies wordt namelijk altijd een vast geheugen address gegenereerd voor een bepaalde functie call. Echter, in het geval van Java of C++ virtual functions kun je compile-time dit address niet bepalen, omdat je niet het echte type van een object weet. Pas runtime weet je waar in de inheritance-chain je zit. Je vtable bevat pointers naar de juiste functies (dus naar die van een sub class, als het object at runtime een sub is ipv de base). Dit is het hele principe van polymorfisme: Een sub kunnen gebruiken waar een base verwacht wordt.
Overal buiten de scope van de interface zelf.
Ok, dat is duidelijk.

Je hebt dus dat interface type helemaal niet nodig O-)

Want, als niemand, maar dan ook echt helemaal niemand die interface kent, dan zal dus ook niemand hem verwachten en dus nodig hebben.

Wat je dus wilt is slechts die functies van het object aanroepen die ook in de interface voorkomen die alleen jij kent en de maker van het object. Maar dan heb je toch die hele interface definitie niet nodig en roep je 'gewoon' via reflection de methoden aan die jij hard uit je hoofd kent. Toch? :?
Laat ik nou nét van plan zijn daar te gaan studeren. /-\o_ :D /-\o_
Maar in welk opzicht?
In Nijmegen wordt functioneel programmeren als de 'normale' programmeer taal geleerd. Wat je bij alle andere universiteiten bij vakken als Inleiding Programmeren krijgt wordt in Nijmegen expliciet Imperatief Programmeren genoemt. Natuurlijk worden machine architectuur enzo wel bekeken, maar de nadruk zal er (denk ik) niet op liggen daar.

  • Eelis
  • Registratie: Januari 2003
  • Laatst online: 21-02-2015
Geen matches
.

[ Voor 106% gewijzigd door Eelis op 18-02-2015 20:01 ]


Verwijderd

Topicstarter
Matched: java
Verwijderd schreef op 18 juni 2004 @ 00:27:
[...]


Sommige concepten, zoals memory layout en eigenlijk het hele imperatieve model komen gewoon rechtstreeks voort uit de opbouw van de machine. Java wordt in 99% van de gevallen naar dezelfde machine gecompileert; de JVM. Deze is weliswaar meestal virtueel, maar volgt nog steeds het Von Neumann model. Het mapt dan ook redelijk naar de huidige computer architecturen. Soms zelfs een beetje -te- direct. In de JVM zijn variable reads en writes atomair, behalve voor Doubles. Dit vanwege mappings naar een echte machine.
OK, maar ik controleer die machine dus niet (volledig).
[...]


Juist ja... ergens geloof ik het niet helemaal ;)
Ik houd je niet tegen. ;)
[...]


Ik snap niet helemaal wat je met class vs Class bedoelt. Kwa data members geldt het echter voor alles wat maar een memory layout heeft.
Zie: http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Class.html
In C++ kun je bv een object 'met de hand' in een leeg stukje geheugen opbouwen.

Bv, hier een vb. (kenners van de win32 API herkennen dit wel :) )

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
BYTE* pData ;
RGNDATA* pRgnData ;
RECT* pRect ;
                    
// create RGNDATA structure 'manually'
pData = new BYTE[ sizeof( RGNDATAHEADER ) + sizeof( RECT ) * iCount ];      
pRgnData = ( RGNDATA* )pData ;

// first element of RECT array
pRect = ( RECT* )( pData + sizeof( RGNDATAHEADER ) ) ;
                    
// set fields of header
pRgnData->rdh.dwSize    = sizeof( RGNDATAHEADER  ) ;
pRgnData->rdh.iType     = RDH_RECTANGLES ;
// ...


[...]


Bytecode is redelijk assembly-like hoor, en werkt dus wel zeer zeker expliciet met 'pointers'. Om dit niveau worden dat echter geen pointer genoemt, maar valt het onder een addressing mode zoals bv Register deferred of indirect.
Hehe, ok, maar nogmaals... ik kan zo low-level niet komen (zonder vuile truuks tenminste ;)).
[...]


Als 2 classes dezelfde memory layout voorschrijven dan hebben objecten van die classes ook precies dezelfde offset tov het address van de pointer. Het bepalen van welke offset welke data member heeft IS namelijk wat de memory layout bepaalt. :)
Dat maakt de offsets echter nog niet gelijk. ;)
Dat kan natuurlijk ook helemaal niet... maar aangezien ik het type niet ken, is dat vrij vervelend.
In C++ werkt het overigens iets gecompliceerder, omdat je verschillende base classen kunt hebben, en er natuurlijk maar eentje op offset 0 van address waar de pointer naar verwijst kan beginnen.
OK, maar dit is niet relevant voor Java... :P
[...]


Ok, dat is duidelijk.

Je hebt dus dat interface type helemaal niet nodig O-)

Want, als niemand, maar dan ook echt helemaal niemand die interface kent, dan zal dus ook niemand hem verwachten en dus nodig hebben.
Zoals ik al duidelijk heb proberen te maken is er een verschil tussen wat ik als programmeur zijnde ken, en wat de JVM kent.

Hoezo heeft niemand (geen enkele class bedoel je neem ik aan) hem nodig omdat hij hem niet kent (het type neem ik aan)? :?

De code is er volledig op toegespitst hoor, er is alleen nog maar een officiele implementation nodig, in feite dus een daadwerkelijke inheritance van de interface tav mijn subclass.
Wat je dus wilt is slechts die functies van het object aanroepen die ook in de interface voorkomen die alleen jij kent en de maker van het object. Maar dan heb je toch die hele interface definitie niet nodig en roep je 'gewoon' via reflection de methoden aan die jij hard uit je hoofd kent. Toch? :?
Ik kan geen methoden uit een interface aanroepen, aangezien deze geen daadwerkelijke code bevatten (zoals je weet). Ik zal de class dus moeten inheriten, oftewel de interface implementen.

Ik wil via die interface die implementors op de hoogte houden van een soort van events, lijkt me gesneden koek.

Maar ik heb al gezegd dat er geen praktisch probleem meer is, dus er vált niets op te lossen. (15e keer dat ik het zeg denk ik :P)
[...]


In Nijmegen wordt functioneel programmeren als de 'normale' programmeer taal geleerd. Wat je bij alle andere universiteiten bij vakken als Inleiding Programmeren krijgt wordt in Nijmegen expliciet Imperatief Programmeren genoemt. Natuurlijk worden machine architectuur enzo wel bekeken, maar de nadruk zal er (denk ik) niet op liggen daar.
Zoals het hoort. _/-\o_

Maar dat ligt er denk ik ook aan welke studie je gaat volgen. Als je technische informatica oid wil gaan doen heb je momenteel weer meer aan imperatieve talen.

Verwijderd

Geen matches
offtopic:
[quote]Eelis schreef op 18 juni 2004 @ 03:15:
Dit was misschien vroeger zo, maar nu niet meer. Ik studeer Informatica in Nijmegen, heb het eerste jaar er nu bijna op zitten, en ben (op school) nog niet geintroduceerd tot functionele programmeertalen. Voor de programmeervakken wordt in het eerste jaar voornamelijk C++ gebruikt.[/quote]

Interesant, maar het zat er natuurlijk wel in, je kunt zo'n starre houding niet vol blijven houden. Ik begreep dat Nijmeegse studenten ook een slechte naam begonnen te krijgen, zo van: "Oh iemand uit Nijmegen, waardeloos, die wil alles in clean gaan maken". Mischien onterecht, maar toch...

Verwijderd

Matched: java
Verwijderd schreef op 18 juni 2004 @ 18:04:
Zoals ik al duidelijk heb proberen te maken is er een verschil tussen wat ik als programmeur zijnde ken, en wat de JVM kent.

Hoezo heeft niemand (geen enkele class bedoel je neem ik aan) hem nodig omdat hij hem niet kent (het type neem ik aan)? :?
Dat is heel simpel. Als er in geen enkel stukje code, waar dan ook, in welke package dan ook, in een static function of niet, dynamisch ingeladen of niet, eventueel dynamisch gegeneerd (door een java source file te genereren en te compilen) enz enz... een verwijzing naar het type staat, dan is dat type gewoon niet nodig.

Ik bedoel dus niet of het type in de code resolved is (gevonden kan worden), maar gewoon of er een verwijzing naar staat. Nou, als dat NERGENS zo is, dan is er dus absoluut geen enkele denkbare situatie waar je het object toch als het type van je onbekende interface wilt hebben.

Bv

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
public interface IUnknown { // onbekende interface die alleen cynarite kent
    public int doIt();
}

public class UnknownImpl { /* class die IUnknown zou moeten implementen, maar wat helaas niet kan */ 
    public int doIt() { return 1;}
}

// code

public class SomeClass {

    public int someFunc () {

        //  laad IUnknownImpl dynamisch op welke manier dan ook, bv:
        Class myUnKnownImpl = Class.forName("UnknownImpl");

        // ... other code  

    }
}

// code in een functie in SomeClass, of andere class, dynamisch geladen, andere package, andere computer, whatever...

public void needIUnknown ( IUnknown unknown ) {
    // ...
    unknown.doIt();

}


Als je goed naar deze code kijkt, dan zie je dat er een functie is die een IUnknown verwacht. Dat is de reden dat je je geinstantieerde UnknownImpl class als een IUnknown wilt hebben. Als nergens in alle code bij elkaar een IUnknown nodig is dan wordt die dus niet gebruikt, en kan ie weggelaten worden.

Je kunt wel via reflection methodes aan willen roepen op UnknownImpl, mischien zelfs wel precies die methodes die in IUnknown gedefineerd staan, maar een IUnknown pointer zelf heb je niet nodig. Per definitie niet, als de naam in je gehele source niet voorkomt en ook nooit voor zal komen in welke dynamische geladen code dan ook.

Bekijk het eens andersom:

Je hebt een object van het type UnknownImpl, en met veel pijn en moeite heb je eindelijk er een IUnknown van kunnen maken. Wat dan? Wat kun je dan wat je eerst niet kon? Je kan het object niet doorgeven aan een functie die IUnknown verwacht, want je stelde zelf al dat die niet bestond. Wil je mischien de enigste functie doIt() gaan aanroepen? Maar dat kon ook al voordat je object als IUnknown gezien werd, namelijk UnknownImpl heeft precies die functie.

Bekijk het nog eens anders:

Ik voeg aan een bestaand Java project de interface "DitIsEenRareInterface" toe. Geen enkele code in het hele project kent en gebruikt deze interface. Ik zelf overigens wel, en diegene die de code schreef kent de interface ook, maar in geen enkel statement of function signature of wat dan ook komt de naam "DitIsEenRareInterface" voor. Wat is het nut van deze interface?
Ik wil via die interface die implementors op de hoogte houden van een soort van events, lijkt me gesneden koek.
Maar dan is er toch wel code die de interface gebruikt? :? :? :?
Als jij via die interface implementors wilt benaderen, dan gebruikt jou code toch die interface???
Maar ik heb al gezegd dat er geen praktisch probleem meer is, dus er vált niets op te lossen. (15e keer dat ik het zeg denk ik :P)
Nou, laten we er dan nog een 16de keer van maken ;)



Er is geen practisch probleem meer, deze discussie is puur theoretisch!



Zo, als ze het nu nog niet weten! :+

[ Voor 3% gewijzigd door Verwijderd op 18-06-2004 21:26 ]


Verwijderd

Geen matches
*lach* Ik geloof dat iedereen het nu maar opgegeven heeft?

Er bleek toch op het laatst dat er echt geen touw meer aan vast te knopen viel. Eerlijk gezegd is me nu toch nog steeds niet duidelijk wat de TS nu precies bedoelde.

Verwijderd

Topicstarter
Geen matches
Zoals ik al zei heb ik een aantal werkzaamheden met een wat hogere prioriteit op het moment, de vakantie staat voor de deur en dus kijk ik er ASAP naar.

Verwijderd

Topicstarter
Matched: java
Zo, mijn vakantie is aangebroken, ik heb eens de tijd genomen om serieus op je post in te gaan. :)
Verwijderd schreef op 18 juni 2004 @ 21:23:
[...]


Dat is heel simpel. Als er in geen enkel stukje code, waar dan ook, in welke package dan ook, in een static function of niet, dynamisch ingeladen of niet, eventueel dynamisch gegeneerd (door een java source file te genereren en te compilen) enz enz... een verwijzing naar het type staat, dan is dat type gewoon niet nodig.

Ik bedoel dus niet of het type in de code resolved is (gevonden kan worden), maar gewoon of er een verwijzing naar staat. Nou, als dat NERGENS zo is, dan is er dus absoluut geen enkele denkbare situatie waar je het object toch als het type van je onbekende interface wilt hebben.
Ik zie niet in hoe je tot die conclusie komt...
Er staat dus wél een verwijzing, aangezien ik deze Interface wil implementen, maar helaas mag die verwijzing er niet staan (ivm correctheid syntax Java).
Bv

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
public interface IUnknown { // onbekende interface die alleen cynarite kent
    public int doIt();
}

public class UnknownImpl { /* class die IUnknown zou moeten implementen, maar wat helaas niet kan */ 
    public int doIt() { return 1;}
}

// code

public class SomeClass {

    public int someFunc () {

        //  laad IUnknownImpl dynamisch op welke manier dan ook, bv:
        Class myUnKnownImpl = Class.forName("UnknownImpl");

        // ... other code  

    }
}

// code in een functie in SomeClass, of andere class, dynamisch geladen, andere package, andere computer, whatever...

public void needIUnknown ( IUnknown unknown ) {
    // ...
    unknown.doIt();

}


Als je goed naar deze code kijkt, dan zie je dat er een functie is die een IUnknown verwacht. Dat is de reden dat je je geinstantieerde UnknownImpl class als een IUnknown wilt hebben. Als nergens in alle code bij elkaar een IUnknown nodig is dan wordt die dus niet gebruikt, en kan ie weggelaten worden.
Maar hoe kom je er bij dat IUnknown nergens in alle code bij elkaar nodig is? :?

Nogmaals, ik laad geen class in die zelf al IUnknown implement, ik heb zelf een class (als code) die ik zelf IUnknown wil laten implementen.
Je kunt wel via reflection methodes aan willen roepen op UnknownImpl, mischien zelfs wel precies die methodes die in IUnknown gedefineerd staan, maar een IUnknown pointer zelf heb je niet nodig. Per definitie niet, als de naam in je gehele source niet voorkomt en ook nooit voor zal komen in welke dynamische geladen code dan ook.
Ik schrijf dus zelf UnknownImpl, zoals ik duidelijk heb vermeld. Dus, de naam komt wel voor, alhoewel dus de vraag is of dat de manier is om mijn doel te bereiken aangezien dit niet mogelijk lijkt.
Bekijk het eens andersom:

Je hebt een object van het type UnknownImpl, en met veel pijn en moeite heb je eindelijk er een IUnknown van kunnen maken. Wat dan? Wat kun je dan wat je eerst niet kon?
Dat is al helemaal geenszins wat ik wil\zeg. :D
Je kan het object niet doorgeven aan een functie die IUnknown verwacht, want je stelde zelf al dat die niet bestond. Wil je mischien de enigste functie doIt() gaan aanroepen? Maar dat kon ook al voordat je object als IUnknown gezien werd, namelijk UnknownImpl heeft precies die functie.
Hehe, dat begrijp ik wel, maar je laat nu wel je fantasie de vrije loop, dit is (idd) niet waar ik het over heb. Maar bedankt voor je uiteenzetting. _O_
Bekijk het nog eens anders:

Ik voeg aan een bestaand Java project de interface "DitIsEenRareInterface" toe. Geen enkele code in het hele project kent en gebruikt deze interface. Ik zelf overigens wel, en diegene die de code schreef kent de interface ook, maar in geen enkel statement of function signature of wat dan ook komt de naam "DitIsEenRareInterface" voor. Wat is het nut van deze interface?
Dat is er niet, maar ik stel duidelijk dat ik deze Interface wél wil gebruiken. Dit kan alleen niet als ik het type niet ken, zo krijg ik de indruk.

Is toch zo klaar als een klontje?
[...]


Maar dan is er toch wel code die de interface gebruikt? :? :? :?
Als jij via die interface implementors wilt benaderen, dan gebruikt jou code toch die interface???
Precies. Waar ontken ik dat dan? :?
[...]


Nou, laten we er dan nog een 16de keer van maken ;)



Er is geen practisch probleem meer, deze discussie is puur theoretisch!



Zo, als ze het nu nog niet weten! :+
Na deze kick zal er wel weer een lading Spuit Elven binnen komen stormen... :P

Verwijderd

Geen matches
Niemand die nog een poging waagt? Waar zijn de helden van P&W gebleven?


.oisyn? alarmnummer? whoami?

Of denken jullie allemaal dit het een hopeloze queste is? :)

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

Alarmnummer

-= Tja =-

Geen matches
Verwijderd schreef op 01 juli 2004 @ 11:10:
Niemand die nog een poging waagt? Waar zijn de helden van P&W gebleven?

.oisyn? alarmnummer? whoami?

Of denken jullie allemaal dit het een hopeloze queste is? :)
Ik vind de discussie iets te kunstmatig van aard en zie het nut er al lang niet meer van in. helaas zijn de laatste tijd de discussies op /14 ook weer zwaar naadje... dus.. tja..

  • whoami
  • Registratie: December 2000
  • Laatst online: 21:13
Geen matches
Ik ben geen held.

https://fgheysels.github.io/


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

Alarmnummer

-= Tja =-

Geen matches
*whoami wordt al bang van een scsi-terminator* :P

Verwijderd

Geen matches
Kom kom. Niet te bescheiden ;)

Verwijderd

Topicstarter
Matched: dynamic
Alarmnummer schreef op 01 juli 2004 @ 11:40:
[...]

Ik vind de discussie iets te kunstmatig van aard en zie het nut er al lang niet meer van in. helaas zijn de laatste tijd de discussies op /14 ook weer zwaar naadje... dus.. tja..
Als iets kunstmatig is is het niet meteen nutteloos. ;)

Ik ga die dynamic proxies eens uitproberen, alhoewel misfire dus ontkende dat dat zou werken.

Misschien is hij bereid om als 'held' op te treden? :? :D

Verwijderd

Matched: java
Verwijderd schreef op 02 juli 2004 @ 00:32:
[...]

Als iets kunstmatig is is het niet meteen nutteloos. ;)
Inderdaad. Sommige mensen willen juist alleen dingen oplossen die een practisch nut hebben, terwijl andere juist weer theoretische dingen willen onderzoeken. Zeker met het oog op nieuwe ontwikkelingen (in bv talen als Java of C++), is het interesant om mogelijke nieuwe styles of syntax te bespreken.

Alleen, hoewel jij stellig vindt van niet en telkens zegt dat wij beter moeten lezen, moet ik toch stellen dat jij echt heel slecht bent in het uitdrukken van een probleem. Ik heb zelf 3 jaar les gegeven in C++ en vaak hadden mensen de meest vreemde ideeen over wat mogelijk moest zijn in een programmeertaal. Ipv, meteen te zeggen, nee dat is fout, dat kan niet, enz, ging ik vaak de discussie aan. Vaak bleek er toch wel een logica in de (voor C++) foutieve gedachtengang te zitten. Ik ben zelf ook actief in het ontwikkelen van een nieuwe taal gebasseerd op 'alternatieve' concepten, dus theoretisch is voor mij wel interesant.

Maar mischien wordt ik te oud, of ben ik niet slim genoeg, maar eigenlijk snap ik nog steeds niet wat je nu wilt. :'(

Is er hier eigenlijk wel iemand die snapt wat onze vriend Cybarite nu eigenlijk bedoeld?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 14-11 23:57

.oisyn

Moderator Devschuur®

Demotivational Speaker

Matched: dynamic
Verwijderd schreef op 02 juli 2004 @ 00:32:
Ik ga die dynamic proxies eens uitproberen, alhoewel misfire dus ontkende dat dat zou werken.
Wat ik een beetje vreemd vind is dat je 100% vertrouwen hebt in die ene reactie van misfire, terwijl je de meeste suggesties van onze kant mbt dynamic proxies een beetje links laat liggen.

Ik denk eerlijk gezegd dat misfire gewoon ongelijk heeft (dat wil zeggen, hij heeft je probleem verkeerd begrepen) en dat dynamics proxies je probleem uitstekend op kunnen lossen :)

[ Voor 6% gewijzigd door .oisyn op 05-07-2004 22:14 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


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

Alarmnummer

-= Tja =-

Matched: java
Verwijderd schreef op 05 juli 2004 @ 21:52:
[...]
Inderdaad. Sommige mensen willen juist alleen dingen oplossen die een practisch nut hebben, terwijl andere juist weer theoretische dingen willen onderzoeken. Zeker met het oog op nieuwe ontwikkelingen (in bv talen als Java of C++), is het interesant om mogelijke nieuwe styles of syntax te bespreken.
Dat is zeker interessant, maar dit topic is eigelijk ook niet meer op dat nivo. Het gaat over een ongelovelijk gekunsteld probleem waarvan ik het nut van de oplossing niet inzie.
Maar mischien wordt ik te oud, of ben ik niet slim genoeg, maar eigenlijk snap ik nog steeds niet wat je nu wilt. :'(
Ik hou het op je leeftijd ;) *nu maar hopen dat jij ouder ben dan ik*

*snapt het zelf ook al lang niet meer*

Verwijderd

Topicstarter
Matched: dynamic
Wat diepgravend weer. :7

@henk_DE_man:
.oisyn had m'n probleem het beste door. Het gaat er om dat je zelf geen dingen moet bijdenken als ik ze niet noem. Dat is geen verwijt, dat doet bijna iedereen, en ik vast ook.

Maar ik heb een paar keer letterlijk gezegd waar ik geinteresseerd (nee, géén probleem ;)) in ben, en dat in soms slechts een paar zinnen...
Dus dan denk ik dat het duidelijk zou moeten zijn...

Maar nogmaals, voor de duidelijkheid:
Opgesomd:
- Ik 'ken' de Interface, dwz: haar classname en gewoon de volledige code (dus ook methods etc.)
- Echter, ik kan deze niet importen
- Ik weet dus heel goed welke methods ik dien te implementen, ik heb in feite een aparte klasse die volledig functioneel is op één ding na: het ontbreekt hem aan een "implements" keyword met daarachter de Interface-naam.

Dus:
- Ik wil runtime aangeven dat die bewuste klasse die Interface moet implementen (ja, ik weet het, als je een method niet/onjuist implement is het "panic" in de VM aangezien je dit niet met de compiler kunt afvangen )
- Ik weet (natuurlijk, anders zou het wel onzinnig zijn) wel de naam van de Interface, en weet de .class file ook te vinden uiteraard.
@.oisyn:
Nou, aangezien zijn verhaal vrij logisch in elkaar zat, en niemand het heeft ontkend.
Dynamic proxies laat ik desondanks niet links liggen:
Ik ga die dynamic proxies eens uitproberen, alhoewel misfire dus ontkende dat dat zou werken.
@Alarmnummer:
Dat heb je al een paar keer gezegd, wat is je probleem daarmee? :?
En waarom heb je het nog steeds over een probleem/oplossing?
Anders vind ik het ook vrij irritant, telkens die overbodige constateringen.

Maar goed, slap gelul allemaal, je komt nooit toe aan de dingen die je wilt doen tijdens vakanties, binnenkort vetrek ik ook voor een tijdje, ik zal die aangedragen suggesties zeker uitproberen, want ik blijf het interessant vinden. :)

[ Voor 4% gewijzigd door Verwijderd op 05-07-2004 22:39 ]


Verwijderd

Geen matches
Alarmnummer schreef op 05 juli 2004 @ 22:10:

Ik hou het op je leeftijd ;) *nu maar hopen dat jij ouder ben dan ik*
Marginaal verschil. Ben 28, begin 1976 (moet maar eens mijn profiel updaten)
*snapt het zelf ook al lang niet meer*
Het vreemde is dat ik eerst het ene zeg en dan zegt hij dat dat ongeveer de bedoeling is, en dan zeg je later het zelfde in iets andere woorden en dan is dat opeens -helemaal- niet de bedoeling, vervolgens leg je de gevolgen neer van het feit dat dat ene niet de bedoeling is en dan is dat ook niet de bedoeling. 8)7

Maar goed, ik geef het officieel op. Veel geluk met je theoretische probleem cybarite! :) Laat je het nog weten als je de oplossing (zelfs al is deze theoretisch) gevonden hebt?

Verwijderd

Topicstarter
Geen matches
Verwijderd schreef op 05 juli 2004 @ 23:53:
[...]

Het vreemde is dat ik eerst het ene zeg en dan zegt hij dat dat ongeveer de bedoeling is, en dan zeg je later het zelfde in iets andere woorden en dan is dat opeens -helemaal- niet de bedoeling, vervolgens leg je de gevolgen neer van het feit dat dat ene niet de bedoeling is en dan is dat ook niet de bedoeling. 8)7
Ehm.. sorry hoor.. maar die samenvatting is een letterlijke kopie van wat ik al eerder postte. Dit was altijd het probleem, en ik heb nooit iets anders gezegd. :?
Maar goed, ik geef het officieel op. Veel geluk met je theoretische probleem cybarite! :) Laat je het nog weten als je de oplossing (zelfs al is deze theoretisch) gevonden hebt?
Het is in principe een doodnormale vraag...
Als niemand een to-the-point antwoord geeft/weet, dan wordt het wellicht een probleem ja. :+

Enfin, jij veel succes met je C++-hobby, iedereen heeft nou eenmaal andere interesses. :)

  • Cuball
  • Registratie: Mei 2002
  • Laatst online: 05-11 10:11
Geen matches
omdat ik in de hele thread niets gelezen heb over spring wou ik dit nog es toevoegen...

Om het probleem van de TS op te lossen kan je perfect gebruik maken van Introductions in Spring.

je kan er via AOP nieuwe functionaliteit aan klassen geven @ runtime.

enkel voorbeelden waarbij je dit zou kunnen doen:
  • wijzigingen van object detecteren (uit Pro Spring boek):
    je wil detecteren of een object gewijzigd is of niet, om niet in elke methode te hoeven controleren of een object gewijzigd is schrijf je hiervoor een simpele Interface met een methode bv: isModified(). Als je dit voor elk object wil doen heb je veel redundante code, en eenmaal abstracte klasse maken verlies je de enige kans op overerving... hier dus ideaal voorbeeld voor icm met AOP (enkel methodes die state kunnen wijzigen hoeven we op te vangen)
  • Alarmnummer had ooit ergens een thread over immutable objecten, ik zou denken dat je hier ook wel wat mee kan aanvangen

"Live as if you were to die tomorrow. Learn as if you were to live forever"


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 14-11 23:57

.oisyn

Moderator Devschuur®

Demotivational Speaker

Geen matches
Hoe lost dat zijn probleem op dan :?

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Cuball
  • Registratie: Mei 2002
  • Laatst online: 05-11 10:11
Geen matches
sorry, ik had iets te snel over het probleem gelezen...

wat ik bedoel is dat je in feite met Spring, snel een klasse een nieuwe Interface kan laten implementeren zonder dat je dit in de code hoeft te doen

maar bij TS is deze zogezegd al geimplementeerd maar wil hij er dynamisch de implements aan toevoegen... denk niet dat dit mogelijk is met spring

"Live as if you were to die tomorrow. Learn as if you were to live forever"


Verwijderd

Matched: dynamic, java
Grappig dat er weer posts zijn in de "mother of all vague threads" ;)

Spring kan idd veel declaratief doen, maar het probleem van de topic starter was eigenlijk meer dat hij het zelf niet wist wat nou precies het probleem was (of dat ik het gewoon niet begreep ;) ).

Met code generation en byte code injection kun je een heel eind komen als je aparte dingen wil doen. In directe JVM byte code is zelfs nog ietsje meer mogelijk dan je met alleen Java zelf kan. Maar het punt was dat de TS wilde dat een object run-time een interface kreeg toebedeeld, terwijl er geen enkel stukje code was wat die interface dan zou gaan aanroepen.

Na de hele thread nog eens doorgelezen te hebben, is het enigste wat ik me kan bedenken dat je de interface als een soort tag gebruikt voor andere reflection gebasseerde code.

In pseudo code

code:
1
2
3
4
5
dynamically inject interface "X" to object
...
in other reflection based code:
   check if object implements interface "X" using reflection
   call methods on object using reflection


Het aparte is dan dat de "other code" zowieso al de methods kon aanroepen via reflection, en dat tevens de methods die uiteindelijk worden aangeroepen door reflection nog niet eens perse diegene zijn die in de interface voorkomen. Je kunt je wel voorstellen dat de interface de methods aan gaat geven die (blind) opgeroepen gaan worden. Dit is enigzins vergelijkbaar met JUnit en een test suite, hoewel je daar geen interface voor hoeft te injecteren.

Bijvoorbeeld (pseudo weer)

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Interface X
   getA()
   getB()   

Object Y   
   getA()
   getB()
   getC()

dynamically inject interface "X" to object Y
...
in other reflection based code:
   check if object implements interface "X" using reflection
   read interface "X" specification
   for all methods i found in specification
      call method i on object using reflection

  • misfire
  • Registratie: Maart 2001
  • Laatst online: 12-10-2024
Matched: dynamic
.oisyn schreef op maandag 05 juli 2004 @ 22:09:
[...]
Wat ik een beetje vreemd vind is dat je 100% vertrouwen hebt in die ene reactie van misfire, terwijl je de meeste suggesties van onze kant mbt dynamic proxies een beetje links laat liggen.

Ik denk eerlijk gezegd dat misfire gewoon ongelijk heeft (dat wil zeggen, hij heeft je probleem verkeerd begrepen) en dat dynamics proxies je probleem uitstekend op kunnen lossen :)
Ik sluit helemaal niet uit dat ik het probleem niet correct snapte in mijn oorspronkelijke reactie en de oplossingen die ik toen gaf. Ik heb in die reactie ook aangegeven dat ik graag wilde dat de TS zijn probleemstelling verder zou toelichten.

Mijn samenvatting van de probleemstelling in de openingspost luidt als volgt:

1. Maak een instantie aan van een klasse X.
2. Wijs de instantie van klasse X toe aan een variabele van een bepaald Interface Y, wat echter niet door klasse X wordt geïmplementeerd.

Volgens mij los je dat niet op met dynamic proxies. (Dynamic) Proxies worden typisch gebruikt om bepaalde pass-through functionaliteit te implementeren om vervolgens een object met dezelfde interface te invokeren, niet om een mapping te maken tussen twee verschillende types. Technisch kan het wel (je kunt alles met dynamic proxies doen), alleen is het mechanisme daar niet voor bedoeld.

Als je zelf at compile time zou weten dat een bepaalde mapping nodig is, dan zou je dat volgens het Adapter patroon met een hulp-object op willen lossen, waarin een expliciete mapping tussen interface Y en klasse X is geïmplementeerd.

Wil je het at runtime doen en je wilt de bovenstaande probleemdefinitie letterlijk oplossen, dan zul je een vorm van bytecode modificatie toe moeten passen. De suggestie van Spring is in dit geval helemaal niet zo vreemd, want het AOP mechanisme van Spring maakt dit soort modificaties ook mogelijk.

Over de eerdere reactie dat een interface en een abstracte klasse gelijk zijn als de abstracte klasse alleen abstracte definities bevat, heb je praktisch gezien gelijk. Maar dat wil niet zeggen dat ik ongelijk heb als ik zeg dat de definitie van het begrip interface anders is dan de definitie van het begrip abstracte klasse. In Brabant hebben we een gezegde: "Als mijn tante een snor had dan was ze mijn oom." Vrij vertaald betekent het zoiets dat het woordje "als" veel verschil uit kan maken. :)

Verwijderd

Matched: java
Geen idee of je dit bedoelt.. maar ik zag het stukje over je interface en classe laden met pluginloader... die gebruik ik ook ! Misschien dat jij er wat aan hebt :)

[rml][ JAVA] ClassCastException bij dynamisch laden classes.[/rml]

Verwijderd

Matched: java
In het licht van deze discussie is het volgende mischien nuttig om te lezen. Dit artikel gaat over precies dit onderwerp:

http://www.coconut-palm-s...itor/2005/04/29#duck_type

Het wordt hier duck typing genoemd.

Een quote uit het artikeltje:
This is exactly what Duck Typing allows us to do—to implement an interface at runtime. So all that remains is to figure out a way to implement this in Java.

In other words, we want to be able to rewrite our constructor to read something like this:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
    public ImageMgr(Object receiver, Image image) {
        if (!DuckType.instanceOf(IImageHolder.class, receiver)) {
            throw new ClassCastException("Cannot implement IImageHolder");
        }

        this.image = image;

    IImageHolder imageHolder = (IImageHolder)
            DuckType.implement(IImageHolder.class, receiver);
    imageHolder.setImage(image);
    imageHolder.addDisposeListener(this);
    }
Pagina: 1 2 Laatste