[alg] meerdere types als return-type.

Pagina: 1
Acties:

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Bij heb aanroepen van een bepaalde methode bij mij kunnen 2 dingen gebeuren:
1) het gaat goed, stuur een object van het ene type terug.
2) het gaat fout, stuur een message terug
De vraag is hoe ik dit het beste kan oplossen. Er zijn een aantal mogelijkheden:

1) zorg ervoor de beide types een gemeenschappelijk supertype hebben. Dit is helaas niet altijd mogelijk omdat een van de types niet te extenden is, bv een String. Verder is het ook niet altijd wenselijk omdat het 2 types zijn die eigelijk niets met elkaar te maken hebben, maar alleen toevallig hier beide als return type kunnen optreden.
2) wrap de beide types in een nieuwe class. Hierbij kan je terplekke een nieuwe class hierarchie maken, bv MessageOrFoo. Dit lijkt dan veel op de union type van c. Het probleem is dat je dan veel overhead hebt (dus ook qua onderhoud) omdat je van dit soort zinloze prutsclasses krijgt.
3) maak het return type Object. Hierdoor kan je van alles terug sturen. Het probleem is dat je dan niet kan zien wat je allemaal terug krijgt. Dus ga je in de toekomst uitbreiden met nog een type bij het returned, dan kan je compile time niet meer checken of alles goed afgehandelt gaat worden.
4) bv een null terugsturen als er iets misgaat en daarna via een extra methode de oorzaak achterhalen, bv. getError. Het probleem is dat dit erg veel problemen op gaat leveren in een multithreaded omgeving.

Ik weet dat dit allemaal supermooi opgeslot kan worden met een echt union/option type. Het probleem is dat de meeste oo talen dit dus niet ondersteunen.,

Voor welke oplossing kiezen jullie dus?

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Iets zegt me dat iedere higher-level taal hier exceptions voor hanteert? :?

Professionele website nodig?


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
curry684 schreef op 02 februari 2004 @ 10:52:
Iets zegt me dat iedere higher-level taal hier exceptions voor hanteert? :?
Oeps.. helemaal vergeten erbij te melden. Exceptions mogen niet opgeworpen worden omdat dit de programma flow helemaal verstoren. Exceptions moet je opwerpen in uitzonderlijke gevallen, maar bij mij is het heel normaal dat er iets fout kan gaan.

*schenkt nog even een dikke bak koffie in*

  • Cuball
  • Registratie: Mei 2002
  • Laatst online: 07:42
gebruik makend van references als parameters (of omweg via pointers) en als return waarde een integer die aangeeft of functie al dan niet geslaagd is ?

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


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

En waarom niet zoals bij COM? Dus een parameter die altijd het resultaat teruggeeft een een return type voor de eventuele foutmelding. Of andersom.

We adore chaos because we like to restore order - M.C. Escher


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
LordLarry schreef op 02 februari 2004 @ 11:13:
En waarom niet zoals bij COM? Dus een parameter die altijd het resultaat teruggeeft een een return type voor de eventuele foutmelding. Of andersom.
Ik ken de COM oplossing niet, zou je die eens willen toelichten?

Verwijderd

Volgens mij bedoelt LordLarry hetzelfde als Cuball...

Ik zie overigens niet in waarom exceptions de programma flow zouden verstoren? Kwestie van op de juiste plaats de exceptions throwen... dan is 't toch geen probleem?
stel:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ReturnObjectVanBepaaldType mijnfunctie() {
  // doe iets
  if( noError )
    return bla;
  else
    throw DitEnDatIsErFoutGegaanException;
}

void main() {
   try {
       mijnfunctie();
   except() {

  }
}


't Is een beetje pseudo code, maar 't gaat om 't idee.. En hier wordt niks geen programma flow verstoord???

Aan de andere kant zijn exceptions dacht ik wel langzamer als if statements, dus in dat geval is Cuball / LordLarry's optie de oplossing...

Een algemeen object als returntype maakt je code verschrikkelijk vaag, dus daar zou ik nooit voor kiezen..

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 10:01

gorgi_19

Kruimeltjes zijn weer op :9

* gorgi_19 doet ook een duit in het zakje..

Is een optie als
Visual Basic .NET:
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
    Private Sub TestValue()

        Dim __customObject As CustomObject = Nothing
        Dim __returnStatus As returnstatus = TestFunction(__customObject)
        '''-----------------------------------------------------------------------------
        ''' <summary>
        ''' Waarde is geaccepteerd, dus __customobject is gevuld
        ''' </summary>
        '''-----------------------------------------------------------------------------
        If __returnStatus = Status.Accepted Then

            '''-----------------------------------------------------------------------------
            ''' <summary>
            ''' Voer acties uit met __customobject
            ''' </summary>
            '''-----------------------------------------------------------------------------
        End If

    End Sub

    Private Function TestFunction(ByRef ObjectToFill As CustomObject) As returnStatus

        ' Voer hier je acties uit

    End Function

Niet een optie? Zo zal objectToFill bijvoorbeeld z'n originele waarde (Nothing) houden als returnstatus 0 is.

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Verwijderd

Als je geen gebruik gaat maken van multithreading lijkt optie 4 mij het elegants. Optie zorgt voor weinig "rommel" in je code (onzin classes etc). Het is ook het mooiste omdat je de "error-checking" (om het maar even zo te noemen) niet ergens onderbrengt (bv een klasse) waar het niet bedoeld is.

Ik zie trouwens niet in waarom dit een probleem oplevert bij multithreading. Zou je mij even willen verlichten door dat uit te leggen?

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Verwijderd schreef op 02 februari 2004 @ 11:23:
Als je geen gebruik gaat maken van multithreading lijkt optie 4 mij het elegants. Optie zorgt voor weinig "rommel" in je code (onzin classes etc). Het is ook het mooiste omdat je de "error-checking" (om het maar even zo te noemen) niet ergens onderbrengt (bv een klasse) waar het niet bedoeld is.

Ik zie trouwens niet in waarom dit een probleem oplevert bij multithreading. Zou je mij even willen verlichten door dat uit te leggen?
Stel dat je een gemeenschappelijk object hebt tussen 2 objecten, bv X. Als er een object wordt aangemaakt op X (en dat gaat niet goed) door thread1 dan staat bij X het bericht klaar voor thread1. Stel dat voordat dat bericht wordt uitgelezen, thread 2 eraankomt en die maakt ook een fout object aan. Je bent nu het bericht van thread 1 kwijt.

[ Voor 3% gewijzigd door Alarmnummer op 02-02-2004 11:28 ]


  • py.mosjuh
  • Registratie: Oktober 2002
  • Laatst online: 24-10-2022

py.mosjuh

fikkert.net

Alarmnummer schreef op 02 februari 2004 @ 10:49:
3) maak het return type Object. Hierdoor kan je van alles terug sturen. Het probleem is dat je dan niet kan zien wat je allemaal terug krijgt. Dus ga je in de toekomst uitbreiden met nog een type bij het returned, dan kan je compile time niet meer checken of alles goed afgehandelt gaat worden.
Gewoon instanceof gebruiken lijkt me voldoende. Echter denk ik uit je verhaal op te maken dat je @runtime wil proberen om een willekeurige class uit te lezen. Dan zou je idd iets van een superclass moeten hebben die dezelfde reeks functies garandeerd.

Het is trouwens mogelijk om @runtime een object te vragen om zijn functies (welke je dus kan gebruiken). Echter weet ik daar zelf niets van, een ex-studiegenoot heeft daar mee gewerkt op zijn afstuderen. Misschien dat dat iets voor je is?

Kites rise highest against the wind - not with it (Winston Churcill)


Verwijderd

Alarmnummer schreef op 02 februari 2004 @ 11:26:
[...]


Stel dat je een gemeenschappelijk object hebt tussen 2 objecten, bv X. Als er een object wordt aangemaakt op X (en dat gaat niet goed) door thread1 dan staat bij X het bericht klaar voor thread1. Stel dat voordat dat bericht wordt uitgelezen, thread 2 eraankomt en die maakt ook een fout object aan. Je bent nu het bericht van thread 1 kwijt.
Dat ik dat zelf niet kon bedenken 8)7 Nou ja, weer wat geleerd.

Je zou in theorie dus (als je van tevoren weet dat het een multi-threaded app wordt) met een array van error-messages kunnen werken (en dan mbv van counters etc) maar dat wordt wel weer erg onelegant en rommelig.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Verwijderd schreef op 02 februari 2004 @ 11:35:
[...]

Dat ik dat zelf niet kon bedenken 8)7 Nou ja, weer wat geleerd.

Je zou in theorie dus (als je van tevoren weet dat het een multi-threaded app wordt) met een array van error-messages kunnen werken (en dan mbv van counters etc) maar dat wordt wel weer erg onelegant en rommelig.
Ik probeer dat builder object stateless te houden. Doordat het dus zelf niet naar objecten kan verwijzen (of alleen naar objecten die immutable zijn), hoef ik me nergens meer druk over te maken en kan het aan iedereen doorgeven.

En verder is de kans groot dat dit systeem in de toekomst in een multi-threaded omgeving gebruikt gaat worden.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Alarmnummer schreef op 02 februari 2004 @ 11:13:
[...]

Ik ken de COM oplossing niet, zou je die eens willen toelichten?
COM retourneert op iedere functiecall een COM-returncode (numeriek). Zie bijvoorbeeld IUnknown::QueryInterface: 2 parameters, en een HRESULT als returnvalue. De eerste parameter is een pointer naar een IID, en de tweede een pointer-pointer naar de resulting interface, waar je dus het resultaat feitelijk in terug krijgt :)

Professionele website nodig?


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
curry684 schreef op 02 februari 2004 @ 12:31:
[...]

COM retourneert op iedere functiecall een COM-returncode (numeriek). Zie bijvoorbeeld IUnknown::QueryInterface: 2 parameters, en een HRESULT als returnvalue. De eerste parameter is een pointer naar een IID, en de tweede een pointer-pointer naar de resulting interface, waar je dus het resultaat feitelijk in terug krijgt :)
Je misbruikt dan een argument als return waarde. Dat is idd een oplossing, maar helaas niet mogelijk in talen waar je niet rechtstreeks met pointers werkt zoals bij Java.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Alarmnummer schreef op 02 februari 2004 @ 12:33:
[...]
Je misbruikt dan een argument als return waarde.
Misbruiken is zo'n lelijk woord... het is afaik de enige manier om meerdere verschillende returnvalues uit een functie terug te krijgen :)
Dat is idd een oplossing, maar helaas niet mogelijk in talen waar je niet rechtstreeks met pointers werkt zoals bij Java.
Heeft Java geen references? :?

En ondanks alles zou ik in jouw geval nog steeds exceptions gebruiken met gerichte catches op de goede plekken :)

Professionele website nodig?


  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
Alarmnummer schreef op 02 februari 2004 @ 10:49:
Ik weet dat dit allemaal supermooi opgeslot kan worden met een echt union/option type. Het probleem is dat de meeste oo talen dit dus niet ondersteunen.,
Bedoel je met option de
Haskell:
1
2
data Maybe a = Just a
             | Nothing

Alleen zie ik niet helemaal hoe je dit kan uitbreiden naar > 2 opties netjes.
Desnoods zou je nog een tupel-idee op kunnen zetten voor de return types

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Glimi schreef op 02 februari 2004 @ 13:15:
[...]

Bedoel je met option de
Haskell:
1
2
data Maybe a = Just a
             | Nothing

Alleen zie ik niet helemaal hoe je dit kan uitbreiden naar > 2 opties netjes.
Desnoods zou je nog een tupel-idee op kunnen zetten voor de return types
Een echt union of option type kan je aangeven welke types uit gekozen mogen worden, bv (int,String,Persoon). En dan zou je eventueel met een switch achtig commando weer kunnen dispatchen hierop:

code:
1
2
3
4
5
swich(result){
   case int : ....;
   case String: ...;
   case Persoon: ..;
}


Bij Nice doen ze dit ook. Je kan een option type maken voor een Object type (null is geen waarde van Object type hier) en Null type (waarmee je dus die mooie compiletime checks voor nullpointers hebt). En daarna ga je met een speciale ifconstructie kiezen uit Null of Object type. Je zou met dat switch case commando ook compiletime kunnen checken of alle types worden afgehandeld en een foutmelding opwerpen als het niet zo is.

[ Voor 4% gewijzigd door Alarmnummer op 02-02-2004 13:28 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 04:03
curry684 schreef op 02 februari 2004 @ 12:41:
Heeft Java geen references? :?
Je kunt alleen references naar objecten hebben (en geen references naar variabelen, bijvoorbeeld). Als het object in kwestie dan immutable is (zoals heel veel simpele klassen als Strings, ints, etcetera in Java) dan kun je 'm wel by reference passen maar kun je er nog steeds niets in stoppen.

Als je nu een reference naar een variable zou kunnen maken, zou je er nog wat mee kunnen:
Java:
1
2
3
4
5
6
7
8
9
10
11
String value;
if(foobar(&value) == 0)
    System.out.println(value);

[..]

int foobar(String &var)
{
    var = "baz!";
    return 0;
}

Maar daar heb je praktich gezien niets aan, want het kan niet.

[ Voor 5% gewijzigd door Soultaker op 02-02-2004 13:50 ]


  • NDF82
  • Registratie: Januari 2002
  • Laatst online: 07:53

NDF82

Doomed Space Marine

curry684 schreef op 02 februari 2004 @ 12:41:
Heeft Java geen references? :?
Tuurlijk wel, alle objecten die meegegeven worden aan een functie zijn references. Alleen van de primitieve types wordt een kopie meegegeven, maar daar zijn weer wrappers voor.


edit: lees net Soultakers verhaaltje, kzal wel mis zijn...

[ Voor 10% gewijzigd door NDF82 op 02-02-2004 13:55 ]

Pentium 233MHz MMX + Diamond Monster 3D 3DFX Voodoo II


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Alarmnummer schreef op 02 februari 2004 @ 11:13:
Ik ken de COM oplossing niet, zou je die eens willen toelichten?
Delphi:
1
function  GetRenderInfo(out plRenderInfo: Integer): HResult; stdcall;


HResult geeft een foutcode aan of S_OK als alles goed gaat. Via de gewonen parameters wordt het resultaat van de functie gegeven. Je zou HResult door een String kunnen vervangen in jouw geval.

Delphi vertaald dit naar een meer normale aanroep en genereerd een exceptie als HResult niet S_OK is.
Delphi:
1
function  GetRenderInfo: Integer; safecall;

We adore chaos because we like to restore order - M.C. Escher


  • Apollo_Futurae
  • Registratie: November 2000
  • Niet online
Glimi schreef op 02 februari 2004 @ 13:15:
[...]

Bedoel je met option de
Haskell:
1
2
data Maybe a = Just a
             | Nothing

Alleen zie ik niet helemaal hoe je dit kan uitbreiden naar > 2 opties netjes.
Desnoods zou je nog een tupel-idee op kunnen zetten voor de return types
In b.v. haskell zou je dit doen met
Haskell:
1
2
3
data Either a b
  = Left a
  | Right b
(standaardtype, zijn veel handige functies voor, is ook een monad)

Aangezien je echter een oplossing in java nodig hebt, is het misschien een idee om de tag van de titel dat aan te laten geven?

Pas de replâtrage, la structure est pourrie.


  • muba
  • Registratie: April 2002
  • Laatst online: 19-10-2013

muba

Prince of Persia!

Noot vooraf: ik heb niet het hele topic doorgelezen, maar wel de helft ofzo.

Ik weet niet in welke taal je dit wil bereiken, of dat je gewoon een theoretische discussie op gang wil brengen, maar wat dacht je van arrays?
Ikzelf stel me de samenstelling dan als volgt voor: eerst een boolean of integer ofzo die aangeeft of de operatie al dan niet succesvol is verlopen (1=succesvol, 0=foutief) en als tweede item de eigenlijke returnwaarde, indien de flag 1 is. Als de flag 0 is kun je ervoor kiezen het tweede item weg te laten of gewoon een lege string / een null-waarde plaatsen.

Reporter: Mister Gandhi, what do you think of western civilisation?
Gandhi: I think it would be a good idea


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 04:03
Om de mogelijkheden een beetje te beperken: is het een groot probleem dat er met Object references gewerkt wordt? In Java 1.4 ontkom je daar in een enigszins ingewikkelde situatie toch niet aan.

Je zou dan namelijk optie 2 kunnen gebruiken met een algemene klasse voor return values, waar een foutmelding (staat die wel vast?) of een echte waarde in gaat. De echte waarde is dan een Object die je nog naar een specifiek type moet casten. Daar kleven wel wat nadelen aan (je moet elke keer checken welke van de waarden geldig is, je moet de juiste casts uitvoeren en dat is weer vervelend met primitive types) maar je kunt de oplossing later, in Java 1.5, zonder veel problemen migreren naar een typesafe oplossing.

Heel veel meer kan ik er helaas niet van maken, ben ik bang. ;)

[ Voor 10% gewijzigd door Soultaker op 02-02-2004 15:43 ]

Pagina: 1