Re: [Seed7-users] Dynamic dispatch strange behaviour
Interpreter and compiler for the Seed7 programming language.
Brought to you by:
thomas_mertes
From: Thomas M. <tho...@gm...> - 2008-02-11 21:49:24
|
"Leonardo Cecchi" <leo...@gm...> wrote (off-list): > I've another question about dynamic dispatching. > In the new chapter you say: > > "Although there is a 'draw' function declared for 'circle' it is not > called directly. Instead the 'draw' interface function for 'shape' is > called. When the program is analyzed (in the interpreter or compiler) > *interface functions take precedence over normal functions* when both > are to be considered." > > I've made a little test: > > $ include "seed7_05.s7i"; > > const type: strangeInterface is new interface; > const func string: getNome(in strangeInterface param) is DYNAMIC; > > const type: astronave is new struct > var string: nome is ""; > end struct; > type_implements_interface(astronave, strangeInterface); > > const type: astronaveBetter is sub astronave struct > var integer: power is 0; > end struct; > type_implements_interface(astronaveBetter, strangeInterface); > > const func astronave: astronave(in string: nome) is func > result > var astronave: result is astronave.value; > begin > result.nome := nome; > end func; > > const func string: getNome(in astronave: a1) is func > result > var string: result is ""; > begin > result:=a1.nome; > end func; > > const func astronaveBetter: astronaveBetter(in string: nome, in > integer:power) is func > result > var astronaveBetter: result is astronaveBetter.value; > begin > result.nome := nome; > result.power := power; > end func; > > const func string: getNome(in astronaveBetter: a1) is func > result > var string: result is ""; > begin > result:=a1.nome & " better"; > end func; > > const proc: main is func > local > var astronaveBetter: myBetter is astronaveBetter("Enterprise > galactica ", 1500); > var strangeInterface: enterprise is astronave.value; > var astronave: myAstro is astronave.value; > begin > enterprise:=myBetter; > myAstro:=myBetter; > > writeln(getNome(enterprise)); > writeln(getNome(myAstro)); > end func; > > The output of this program is the following: > > C:\msys\1.0\home\lcecchi\seed7\src>hi provatre.sd7 > HI INTERPRETER Version 4.5.3082 Copyright (c) 1990-2008 Thomas Mertes > 259 C:/msys/1.0/home/lcecchi/seed7/lib/syntax.s7i > 3395 C:/msys/1.0/home/lcecchi/seed7/lib/seed7_05.s7i > 55 provatre.sd7 > 3709 lines total > 119645 lines per second > 1673829 bytes > Enterprise galactica better > Enterprise galactica > > I don't understand why it doesn't do a dynamic dispatching on the > second instruction. > The functions to be considered are: > > const func string: getNome(in strangeInterface param) is DYNAMIC; > const func string: getNome(in astronave: a1); > const func string: getNome(in astronaveBetter: a1); > > So the interface should have precedence on the other functions > considering that either "astronave" or "astronaveBetter" implements > the interface "strangeInterface". > I haven't understood something... Where I'm wrong? > Thanks, > > Leonardo The local variable 'myAstro' has the type 'astronave' which is a structure. Assignments of structures do a (deep) copy. The struct 'astronaveBetter' has more elements than 'astronave', but only the elements present in both structures are copied. The assignment 'myAstro:=myBetter' does a copy of the structure (The element 'nome' is copied). With that copy the information that 'myBetter' had the type 'astronaveBetter' is lost. My description of the process: "Although there is a 'draw' function declared for 'circle' it is not called directly. Instead the 'draw' interface function for 'shape' is called. When the program is analyzed (in the interpreter or compiler) *interface functions take precedence over normal functions* when both are to be considered." is right, but does not have the desired effect here. The variable 'myAstro' is not a reference to a value, but the value itself. The process described above makes sense for parameters (except for a value parameter where the value is copied). For structs the parameters 'in', 'ref' and 'inout' are reference parameters. In this cases a parameter of type 'astronave' can point to a value of type 'astronaveBetter'. In this cases a parameter of type 'astronave' behaves iside a function (method) like a parameter of type 'strangeInterface'. If you add to your example: const func integer: getPower (in strangeInterface param) is DYNAMIC; const func integer: getPower (in astronave: a1) is return 0; const func integer: getPower (in astronaveBetter: a2) is return a2.power; const func string: getPowerName (in astronave: a1) is return getNome(a1) & "-" & str(getPower(a1)); and add to the main program: writeln(getPowerName(myBetter)); you will get: Enterprise galactica better-1500 which is exactly what you expect. Something is clear now: My description of the process of dynamic dispatch is not precise enough and needs improvement. May be my idea of having value copy for implementation objects and reference copy for interface objects is too confusing. May be I should describe the role of assignments in more detail. What do you think about my concepts and their description? BTW.: If possible I would prefer the discussion to be on see...@li... That way others can also follow the discussion. Greetings Thomas Mertes Seed7 Homepage: http://seed7.sourceforge.net Seed7 - The extensible programming language: User defined statements and operators, abstract data types, templates without special syntax, OO with interfaces and multiple dispatch. -- Psssst! Schon vom neuen GMX MultiMessenger gehört? Der kann`s mit allen: http://www.gmx.net/de/go/multimessenger |