Thanks.
partly. there are the usual transformations like out (String
representation of an object), to_integer, to_double etc in String. But
casts in this sense
int i;
double d;
d := (double) i; are not supported. Of course this is a bad
example because you can assing an INTEGER to a DOUBLE.
Objects have to be conformant. To check if the conformance holds you
can use the assignment Attemp.
Assume you have
class A
end
class B
inherit A
end
then you can do a
a: A
b: B;
a := b
and if you are not sure what it is you can check
b ?= a
if b is unequal void or conformant this will suceed.
The assignment attempt is quite useful e.g. in the NUMERIC hierachy
i_ref is INTEGER_REF;
r_ref is REAL_REF;
d_ref is DOUBLE_REF;
...
try_assignments (other: NUMERIC) is
-- what type is `other', find out with assignment attempt.
do
i_ref ?= other;
r_ref ?= other;
d_ref ?= other;
i_bignum ?= other;
i_rational ?= other;
end;
Now after thos tries you can check
i : INTEGER;
if i_ref /= Void then
-- is is an Integer do you can be sure that this will work
i := i_ref;
I hope I showed how it works.
The conversions and assignments attempt do not work for arbitrary
objects so if you have
class A
end
class B
end
and no relationsship between them you have to write your own
conversion routines.
Hope this helps a bit
Friedrich
Yes, this class will work with ISE eiffel.
Note that this is rarely needed, in most cases a ?= will do.
indexing
description:
"Cast an object to a TARGET_TYPE ignoring conformance.%N%
%eg:%N%
%a: ANY%N%
%l: LINKED_LIST [STRING]%N%
%l := (create {CAST [LINKED_LIST [STRING]}).cast (a)"
keywords: "cast, force"
date: "$Date: 2000/09/26 16:23:42 $"
revision: "$Revision: 1.3 $"
class
CAST [TARGET_TYPE]
inherit
INTERNAL
feature -- Basic operation
cast (a: ANY): TARGET_TYPE is
-- `a' cast to TARGET_TYPE without type check.
do
Result := null_macro ($a)
end
checked_cast (a: ANY): TARGET_TYPE is
-- `a' cast to TARGET_TYPE.
require
type_conforms_to (dynamic_type (a), target_type)
do
Result := null_macro ($a)
end
target_type: INTEGER is
-- Type code of TARGET_TYPE.
do
Result := eif_gen_param_id (-1, $Current, 1)
end
feature {NONE}
null_macro (p: POINTER): TARGET_TYPE is
-- Facilitates assignment without typecheck.
-- foo := null_macro (bar) is Eiffel becomes:
-- foo = (bar); in C.
external
"C [macro <eif_eiffel.h>]"
alias
" "
end
eif_gen_param_id (stype: INTEGER; obj: POINTER; pos: INTEGER):
INTEGER is
-- Type of generic parameter in `obj' at position `pos'.
external
"C (int16, EIF_REFERENCE, int): EIF_INTEGER |
%"eif_gen_conf.h%""
end
end
Sent via Deja.com
http://www.deja.com/
Thanks a lot !!
However i have a little problem when compiling :
compile -o test test make
****** Fatal Error : The $ operator must be followed by the final
name of a feature which is not a constant attribute (VUAR.4).
Line 37 column 46 in CAST (./cast.e) :
Result := eif_gen_param_id (-1, $Current, 1)
^
line 34-38 of cast.e :
<<
target_type: INTEGER is
-- Type code of TARGET_TYPE.
do
Result := eif_gen_param_id (-1, $Current, 1)
end
>>
with the test class :
<<
creation
make
feature
make is
local
a : A
laeticia : CAST[B]
do
!!a;
!!b ;
laeticia.cast(a).test ;
end;
end -- class TEST
>>
Please excuse, first I forgot to say that I compile with SmallEiffel
and second I made a little error in my last post.
my test class is :
> creation
> make
> feature
>
> make is
> local
> a : A
> laeticia : CAST[B]
> do
> !!a;
> !!laeticia ; -- error corrected
> laeticia.cast(a).test ;
> end;
> end -- class TEST
Else, for the previous problem, I replaced '$something'
with 'something.to_pointer.
This time, when compiling, there is a problem with : inherit INTERNAL
****** Fatal Error : Unable to load class.
Line 16 column 4 in CAST (./cast.e) :
INTERNAL
^
I searched for this file but I have not.
Then, when I mask the line inherit INTERNAL :
-- inherit
-- INTERNAL
When compiling :
<<
compile -o test test make
In file included from test1.c:8:
test.h:481: parse error before `a1'
gcc: test1.o: No such file or directory
gcc: No input files
/usr/ccs/bin/sparcv9/strip: test: cannot open file.
No such file or directory
>>
Sam
In article <97972595...@hermes.scinfo.uhp-nancy.fr>,
Wouldn't fixing the conformance checker be better?
(Assuming the poster is Sam O'Connor of ISE fame :)
Eirik Mangseth
Stockpoint Nordic AS
Lysaker, Norway
"If I can't Eiffel in heaven, I won't go"
>
> Wouldn't fixing the conformance checker be better?
> (Assuming the poster is Sam O'Connor of ISE fame :)
Depends on the Way of programming one prefers
- Unix way (don't fix it, patch it)
- do it the right way (fix it, Fix it, FIx it, FIX it) ;-)
Could not resist sorry ;-)
Friedrich
Yes, fixing the conformance checker would undoubtedly be better.
However, there are cases where casting is, IMHO, needed:
- For stylistic reasons: if you know that something is a certain
type because you can infer it from some other known things then
it is cleaner to do a cast than to have a local variable
simply for the purpose of doing an assignment attempt.
A cast compiles away to nothing, an assignment attempt involves
a runtime conformance test.
- Because there is no other way: if you have an agent that returns
INTEGER (or any base type) and you have a reference to it of
type FUNCTION [ANY, TUPLE[], ANY] (return type ANY) and you do
a: ANY; a := agent.item ([]) this is bad.
The integer is written directly into the reference variable `a'.
So if the integer was 7 then `a' now points to memory address 7.
If you know at runtime that the agent will return an INTEGER,
eg from reflection data, you can cast the agent to the correct
type before you call it.
The root of this problem is fundamental flaw in the way base classes
are made to appear like they conform to ANY when they don't really.
Sam
Hmm, and what is the Microsoft way? :-)
>Could not resist sorry ;-)
>Friedrich
--
Jim Cochrane
j...@dimensional.com
>
>
> Hmm, and what is the Microsoft way? :-)
I'm not sure is it maybe
DENY IT, DENY It, DENY it, DENy it, DEny it, Deny it, deny it,
it has been fixed long ago ;-)
Regards
Friedrich